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

求助:如何用非递归方式实现Haskell十进制转八进制函数

非递归实现十进制Int转八进制(Haskell)

方法1:用unfoldr生成余数序列

unfoldr是Haskell里生成列表的非递归工具,刚好适配这种逐步分解数值的场景:

import Data.List (unfoldr)

decimalToOctal :: Int -> String
decimalToOctal 0 = "0"
decimalToOctal n = reverse $ map (head . show) $ unfoldr step (abs n)
  where
    step 0 = Nothing
    step x = Just (x `mod` 8, x `div` 8)
  • unfoldr step (abs n)会反复调用step,每次返回当前值模8的结果,以及更新后的被除数(当前值除以8),直到被除数为0,生成的余数列表是低位到高位的顺序(比如十进制10会生成[2,1])
  • 用reverse反转列表得到正确的高位到低位顺序
  • map (head . show)把每个Int类型的余数转换为字符

方法2:用iterate生成中间值再提取余数

如果不想用unfoldr,可以通过iterate生成所有除以8的中间结果,再过滤提取余数:

decimalToOctal :: Int -> String
decimalToOctal 0 = "0"
decimalToOctal n = reverse $ map (`mod` 8) $ takeWhile (/=0) $ iterate (`div`8) (abs n)
  • iterate (div8) (abs n)生成序列:n, ndiv8, ndiv8div8,...直到出现0
  • takeWhile (/=0)截取到0之前的所有中间值
  • map (mod8)给每个中间值取模8得到余数列表,反转后转成字符串即可

针对你提到的foldr的补充

你之前想用foldr累积单一值的思路不太适配,但可以先生成余数序列,再用foldr拼接成最终字符串:

decimalToOctal :: Int -> String
decimalToOctal 0 = "0"
decimalToOctal n = foldr (\d acc -> show d ++ acc) "" $ reverse remainders
  where
    remainders = unfoldr step (abs n)
    step 0 = Nothing
    step x = Just (x `mod`8, x`div`8)

注:以上函数处理了0和负数的情况(取绝对值转换),如果只需要处理正整数,可去掉abs。

内容的提问来源于stack exchange,提问作者J. G.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 21:57:02