浮点数因二进制无法精确表示十进制小数(如0.1、0.2)而存在舍入误差,导致0.1+0.2==0.3为False;应使用math.isclose()或abs(a-b)

浮点数在计算机里根本存不准
二进制无法精确表示大多数十进制小数,比如 0.1 和 0.2 在 IEEE 754 双精度下都是无限循环二进制小数,存储时被截断。相加后结果是 0.30000000000000004,而不是数学意义上的 0.3。
这不是 Python 的 bug,是所有遵循 IEEE 754 的语言(C、Java、JavaScript 等)共有的底层限制。
直接用 == 比较浮点数几乎总是错的
以下写法在绝大多数场景下都会出问题:
0.1 + 0.2 == 0.3 # False a = 0.1 + 0.2 b = 0.3 a == b # False
- 即使看起来“相等”,只要涉及计算,就可能因舍入误差导致
==返回False -
math.isclose()是 Python 3.5+ 官方推荐方案,它用相对误差 + 绝对误差双阈值判断 - 默认容差是
rel_tol=1e-09、abs_tol=0.0,对大多数场景够用;但科学计算或高精度需求需显式调大abs_tol
math.isclose() 怎么用才靠谱
正确用法示例:
立即学习“Python免费学习笔记(深入)”;
import mathmath.isclose(0.1 + 0.2, 0.3) # True math.isclose(1e-9, 0.0, abs_tol=1e-10) # False(太小了) math.isclose(1e-9, 0.0, abs_tol=1e-8) # True(显式放宽绝对容差)
- 涉及接近零的数时,必须设
abs_tol,否则仅靠相对容差会失效(因为相对误差分母为零或极小) - 不要依赖默认
rel_tol处理数量级差异大的数,比如比较1e-15和1e-5 - 如果项目不支持 Python 3.5+,可用等效逻辑:
abs(a - b)
什么时候该用 decimal 或 fractions
当业务逻辑要求**十进制精度可预测**时(如金融计算、会计、测试断言),float 本身就不该出现:
-
decimal.Decimal('0.1') + decimal.Decimal('0.2') == decimal.Decimal('0.3')→True -
fractions.Fraction(1, 10) + fractions.Fraction(2, 10) == fractions.Fraction(3, 10)→True -
Decimal需传字符串初始化,传float(如Decimal(0.1))会先引入浮点误差,等于白用 - 性能比
float差一个数量级,别在热路径滥用
浮点比较的坑不在语法,而在默认思维——人脑按十进制算,机器按二进制存。绕开它的唯一办法,是每次做比较前,先想清楚:这里到底要“数学相等”,还是“足够接近”。










