问题现象
用 float 做金额累加,最后总额比预期多出几分钱,对账时怎么也对不上。
原因分析
二进制浮点无法精确表示十进制小数,累加误差在多次运算后放大。判断时先分清是 Python 浮点数精度 本身的配置问题,还是上游调用、运行环境带进来的差异;前者改配置就能收口,后者要沿着请求链路一层层往上找,处理顺序不能颠倒。先在出问题的机器上复现一次,把报错原文和发生时间记下来,再对着日志定位。
处理步骤
- 金额统一用 Decimal 并指定精度
- 从字符串构造而不是从 float 转换
- 输出时按分位量化
对应的命令或配置片段如下,可直接复制:
from decimal import Decimal, ROUND_HALF_UP
a = Decimal('0.1') + Decimal('0.2')
print(a, a == Decimal('0.3'))
total = (Decimal('19.99') * 3).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
改动前把原配置备份一份,出问题时能马上回退,比现场找原因省时间。排查时把每一步的输出留下来,后面再遇到同类问题,对照日志就能判断是哪一层先出错的。
验证结果
对账结果与业务系统一致,金额保留两位且没有多余小数。