递归函数,用于将数字中的所有数字相加

时间:2012-05-16 20:46:26

标签: haskell

我正在处理一个函数,该函数将数字中的所有数字相加,并保持累加数字直到数字减少到一位数。例如,应该像这样评估数字99999999999

99999999999
9+9+9+9+9+9+9+9+9+9+9
99
9+9
18
1+8
9

但是,当我尝试通过我的函数运行数字99999999999时,它会返回7,即使它应该返回9。我已经多次查看了我的代码,我想不出任何理由。

以下是代码:

sumdr x
  | x <= 9 = x
  | otherwise = sumdr $ addupnums x

addupnums y = foldl (+) 0 $ map read1 $ show y

read1 :: Char -> Int
read1 '1' = 1
read1 '2' = 2
read1 '3' = 3
read1 '4' = 4
read1 '5' = 5
read1 '6' = 6
read1 '7' = 7
read1 '8' = 8
read1 '9' = 9
read1 '0' = 0
read1 x = error "needs to be a number"

2 个答案:

答案 0 :(得分:6)

这对我来说在64位系统上运行正常。如果您使用的是32位系统,则99999999999不适合Int,因此它会溢出并给您错误的结果。

如果将类型更改为Integer,则应该可以正常工作。

答案 1 :(得分:2)

<强> [编辑]

如果你只对重复申请的结果感兴趣,直到剩下一个数字,当然Daniel Fischer是对的,你应该使用他的解决方案。如果不可能有这样的捷径,如何处理这类问题仍然是有益的,因此我留下了我的旧答案。

<强> [/编辑]

你得到了答案,但有两个评论:

  • 使用Hoogle您可以在digitToInt中找到Data.Char函数,这是read1
  • 将数字转换为字符串只是为了得到数字似乎是浪费,当更多的数学运算也可以,例如。

f 0 = 0
f y = (y `mod` 10) + f (y `div` 10)

或稍微神秘的版本:

f = sum . map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)

如果你真的关心速度,你可以使用divMod,你可以试试累加器是否更快,例如。

f n = go n 0 where
  go 0 s = s
  go k s = go k' (s+s') where (k',s') = k `divMod` 10