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