Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 将整数转换为不带'的数字列表;mod';和';分区';_Haskell - Fatal编程技术网

Haskell 将整数转换为不带'的数字列表;mod';和';分区';

Haskell 将整数转换为不带'的数字列表;mod';和';分区';,haskell,Haskell,我现在有下面的Haskell函数,它将一个整数转换成从原始整数中提取的数字列表。因此,我的问题是:有没有一种方法不使用mod和div就能做到这一点?例如,如果我想用一个字符串做同样的事情,我可以使用其他函数(如head和tail等)创建一个函数 我在这个问题上挣扎了一段时间,最后得出结论,并在另一篇文章中找到了答案。让我问这个问题的是,我从来没有想过自己会使用mod和div toDigits :: Integer -> [Integer] toDigits n | n < 1 =

我现在有下面的Haskell函数,它将一个整数转换成从原始整数中提取的数字列表。因此,我的问题是:有没有一种方法不使用
mod
div
就能做到这一点?例如,如果我想用一个字符串做同样的事情,我可以使用其他函数(如head和tail等)创建一个函数

我在这个问题上挣扎了一段时间,最后得出结论,并在另一篇文章中找到了答案。让我问这个问题的是,我从来没有想过自己会使用
mod
div

toDigits :: Integer -> [Integer]
toDigits n 
 | n < 1 = []
 | otherwise = toDigits (n `div` 10) ++ [n `mod` 10]
toDigits::Integer->[Integer]
托迪金
|n<1=[]
|否则=toDigits(n`div`10)+[n`mod`10]

您提到可以使用列表操作对字符串执行相同的操作。事实上,这将是另一种方式。可以将整数转换为字符串,然后将每个字符转换为整数:

import Data.Char (digitToInt)

toDigits :: Int -> [Int]
toDigits = map digitToInt . show
这里我使用的是
Int
而不是
Integer
,但是如果您真的想麻烦一点,可以使用
Integer

toDigits :: Integer -> [Integer]
toDigits = map (fromIntegral . digitToInt) . show
使用,一种将某些值转换为
字符串
(换句话说,获取其字符串表示形式)的通用方法。值的类型应为typeclass的实例。例如,
Int
Show
的一个实例(在
ghci
中输入
:i Int
,然后查找字符串
实例Show Int--“GHC.Show”中定义)。但是函数不是Show的实例,因此让f中的fn=n将抛出一个错误,因为如何将函数转换为字符串?(另见:)。无论如何,使用
show
函数是惯用的,所以您可以坚持使用它

但是,有一种方法可以使用对数、幂和整数除法从数字中提取数字。请记住,您可以通过查找余数从左侧删除数字,通过整数除法从右侧删除数字。在这两种情况下,右操作数都是10的幂。例如:

*Main> 123 `mod` 10
3
*Main> 123 `div` 100
1
*Main> logBase 10 1000
2.9999999999999996
但是你怎么知道,你应该用10的哪一次方除以呢?通过查找以10为底的对数:#N=log10N+1的数字,例如log1012345=4。不幸的是,您不能使用,因为它使用的是浮点运算,而浮点运算是。例如:

*Main> 123 `mod` 10
3
*Main> 123 `div` 100
1
*Main> logBase 10 1000
2.9999999999999996
您可以使用用于整数的自定义函数将代码从链接复制到源代码中。要找到数字的第一位数字,我使用以下代码:

firstDigit :: (Integral a) => a -> a
firstDigit n = n `div` (10^log)
  where log = fst $ iLogBase 10 n
创建一个查找数字的任意数字并将数字转换为数字列表的更通用的函数作为练习留给您:)

此外,您问题中的代码效率低下。列表串联
(++)
操作具有
O(n)
的复杂性,也就是说,每次您想要在列表中添加元素并结束时,它必须将左侧列表逐个添加到右侧列表,直到您得到一个结果列表。查看
(++)
,基本上
[1,2,3]+[4]
变成
1:2:3:[4]
,效率非常低,因为仅仅添加一个列表就需要3个cons
(:)
操作。当您多次将数字附加到末尾时,每次都必须重复相同的过程,因此函数的总体复杂性是
O(n^2)

另一方面,
(:)
是即时的,即具有
O(1)
的复杂性。无论列表有多长,在元素开头加上前缀都很便宜。因此,我建议不要在末尾添加元素,而是将其添加到开头,并在末尾添加一个元素,只需将列表反转一次即可(有关信息,Lisp人员称之为):