0

我正在开发一个函数,它将一个数字中的所有数字相加,并继续将数字相加,直到数字减少到一个数字。例如,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"
4

2 回答 2

6

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

如果将类型更改为整数,它应该可以工作。

于 2012-05-16T20:53:04.870 回答
2

[编辑]

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

[/编辑]

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

  • 使用Hoogle,您可以在 中找到函数digitToIntData.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
于 2012-05-16T21:19:15.390 回答