You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. 第一次拆分得到[8,8,8],求和为24
  2. 24不是个位数,继续拆分得到[2,4],求和为6
  3. 6是个位数,返回结果6,完美符合你的需求~

内容的提问来源于stack exchange,提问作者D.Grigal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:32:33