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

Python中math.fsum与循环求和结果差32.0的原因探究

为什么Python中math.fsum和循环累加浮点数的结果差32.0?

首先看测试代码:

import math

nums = [26015151255025000.,26015151255025000.,26015151255025000.,26015151255025000.,26015151255025000.,26015151255025000.,26015151255025000.,26015151255025000.,26015151255025000.]

math_fsum_result = math.fsum(nums)

loop_result = 0.0
for n in nums:
    loop_result += n

print(format(math_fsum_result, '.1f'))
print(format(loop_result, '.1f'))

运行输出:

234136361295224992.0
234136361295224960.0

已知用decimal计算的正确值是234136361295225000.0,两种求和方法的结果刚好差32.0,核心原因在于浮点数的精度限制和两种算法的误差处理逻辑差异:

1. 单个浮点数的存储误差

Python的float是64位双精度浮点数,遵循IEEE 754标准,它的尾数部分最多能精确表示53位二进制整数。你的原始数值26015151255025000转换成二进制后,有效位数超过了53位,所以存储为float时会被舍入成26015151255024992.0——比原数小8,这是初始误差来源。

2. 普通循环累加的误差累积

普通累加是逐次把当前结果和下一个数相加,每次相加如果结果无法用双精度精确表示,就会截断低位,丢失的精度会累积:

  • 前几次累加的结果还能被精确表示,但加到第7次之后,当前结果的二进制位数已经很高,再加上下一个数时,较小数的低位会被截断,每次这样的累加都会额外丢失16的精度。
  • 9个数值累加下来,普通累加的总误差是-40(比正确值小40)。

3. math.fsum的误差补偿机制

math.fsum采用了补偿求和算法(类似Kahan求和的优化版本),它会在累加过程中额外跟踪那些被截断的微小误差值,后续累加时会把这些丢失的部分重新加回去,最大程度减少误差累积。

  • 在这个例子里,fsum把单个数值的存储误差(每个-8,共-72)大部分补回来了,最终只比正确值小8,总误差是-8。

差值为32.0的原因

普通累加的总误差是-40,fsum的总误差是-8,两者的误差差就是(-8) - (-40) = 32,所以两个结果刚好相差32.0。这不是巧合,是双精度浮点数的位数限制和两种算法的误差处理逻辑共同导致的。

内容的提问来源于stack exchange,提问作者Firestrand

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:55:59