Haskell实现e^x泰勒递归函数结果不符问题求助
问题分析:整数溢出导致计算错误
你的代码逻辑本身是对的——泰勒级数展开计算e^x确实是累加从k=0到n的x^k/k!,但问题出在大整数溢出上。
Haskell中的Int类型是固定精度的整数(通常是32位或64位),当你计算x^n时,比如10^20,这个值是100000000000000000000,远超过64位Int的最大值(约9e18)。此时整数会溢出,变成一个错误的负数或乱码值,再转成Float后,整个项的计算就完全偏离了正确值,最终导致总和不符合预期。
另外,你的代码每次递归都重新计算factorial n,这会让时间复杂度变成O(n²),效率很低,但这不是结果错误的直接原因。
解决方案:避免大整数溢出
有两种简单的修复方式,推荐第一种(更高效且精度更好):
方法1:递推计算每一项(推荐)
不要每次单独计算x^n和n!,而是利用前一项的结果递推当前项:term_k = term_{k-1} * x / k。这样全程用浮点数计算,完全避开大整数问题,同时时间复杂度降到O(n)。
修改后的代码:
consigna3 :: Int -> Int -> Float consigna3 x n = go n 1.0 0.0 where -- go 当前项的k值 当前项的值 累加和 go 0 term sum = sum + term -- 加上k=0的项(x^0/0! = 1) go k term sum = let nextTerm = term * fromIntegral x / fromIntegral k in go (k-1) nextTerm (sum + term)
方法2:使用任意精度整数
改用Integer类型(Haskell的任意精度整数)来计算x^n和阶乘,避免溢出,之后再转成Float:
factorial :: Integer -> Integer factorial 0 = 1 factorial n = n * factorial (n-1) consigna3 :: Int -> Int -> Float consigna3 _ 0 = 1.0 consigna3 x n = let xInt = toInteger x nInt = toInteger n in (fromIntegral(xInt ^ nInt) / fromIntegral(factorial nInt)) + consigna3 x (n-1)
验证结果
用第一种方法测试你的示例:
consigna3 10 20会返回21991.48左右consigna3 10 30会返回22026.46左右
其他示例也会符合预期。
内容的提问来源于stack exchange,提问作者Ignacio Mauricio Rios
相关产品推荐
相关产品推荐

