Haskell递归问题求助:实现整数各位数字反复求和至个位数
实现迭代到个位数的数字求和(数字根)
嘿,你已经搞定了基础的各位数字求和,现在要把这个逻辑迭代到得到个位数对吧?咱们来一步步优化你的代码,实现这个需求~
首先先看看现有代码里可以简化的地方:你的add函数其实完全没必要,Haskell的标准库sum函数已经能直接计算列表的和了,直接用sum (todigits integer)就能替代add的功能。
接下来是核心的迭代逻辑:我们需要一个递归函数,不断对当前结果求和,直到结果是个位数(小于10)。这个其实就是数学里的数字根(Digital Root),咱们可以写一个专门的函数来实现它。
另外,你的todigits函数在输入0的时候会返回空列表,这会导致求和出错,咱们也顺便修复这个问题,还可以加上对负数的处理(可选,让函数更健壮)。
完整改进后的代码
import System.IO -- 拆分整数为各位数字列表,处理0和负数情况 todigits :: Integral x => x -> [x] todigits 0 = [0] todigits x | x < 0 = todigits (-x) -- 负数转为正数处理 | otherwise = todigits (x `div` 10) ++ [x `mod` 10] -- 计算数字根:迭代求和直到得到个位数 digitalRoot :: Integral x => x -> x digitalRoot x | x < 10 = x -- 已经是个位数,直接返回 | otherwise = digitalRoot . sum . todigits $ x -- 递归计算各位和的数字根 main = do -- 固定输入888的情况 let integer = 888 print $ digitalRoot integer -- 输出6,符合你的预期 -- 如果想要交互式输入(可选替换上面的代码): -- putStrLn "请输入一个整数:" -- input <- getLine -- let integer = read input :: Int -- print $ digitalRoot integer
代码解释
- todigits改进:当输入为0时返回
[0],避免空列表导致求和错误;遇到负数时先转为正数再处理,扩大函数适用范围。 - digitalRoot函数:这是实现迭代求和的核心。如果当前数字是个位数,直接返回;否则递归调用自身,参数是当前数字的各位之和,直到得到个位数结果。
- 简化求和逻辑:去掉了冗余的
add函数,直接用标准库的sum来计算各位数字之和。
测试一下输入888:
- 第一次拆分得到
[8,8,8],求和为24 - 24不是个位数,继续拆分得到
[2,4],求和为6 - 6是个位数,返回结果6,完美符合你的需求~
内容的提问来源于stack exchange,提问作者D.Grigal
相关产品推荐
相关产品推荐

