浮点数无法精确表示0.1和0.2是ieee 754双精度标准的固有局限,因二者在二进制中为无限循环小数;python等语言用53位尾数近似存储,导致0.1+0.2≠0.3,应使用math.isclose()或容差比较。

浮点数在计算机中根本存不准0.1和0.2
这不是Python的bug,而是所有遵循IEEE 754双精度浮点标准的语言(C、Java、JavaScript等)共有的底层限制。0.1和0.2在二进制下是无限循环小数,就像十进制里1/3 = 0.333…无法精确表示一样。Python只能用有限位(53位尾数)去近似存储它们,导致实际存进去的值分别是:
0.1 → 0.1000000000000000055511151231257827021181583404541015625<br>0.2 → 0.200000000000000011102230246251565404236316680908203125
这两个近似值相加后,结果自然不是精确的0.3,而是:
<code>0.1 + 0.2</code> → 0.3000000000000000444089209850062616169452667236328125
直接用==比较浮点数几乎总是错的
这是最常踩的坑:写0.1 + 0.2 == 0.3返回False,然后怀疑Python出问题。实际应该用容差判断:
- 用
math.isclose()(推荐,Python 3.5+):math.isclose(0.1 + 0.2, 0.3)→True - 手动设阈值:
abs((0.1 + 0.2) - 0.3) - 避免在关键逻辑里依赖浮点相等性,比如循环条件、字典键、集合成员判断
需要精确十进制运算时,别硬扛,换工具
金融计算、会计场景必须避免误差,这时float不是选项:
- 用
decimal.Decimal:传字符串初始化,避免浮点污染 ——Decimal('0.1') + Decimal('0.2') == Decimal('0.3')→True - 别写
Decimal(0.1),因为0.1已经是不精确的float,污染已发生 -
decimal有性能开销,且不支持**所有**数学函数(如sin、log),需权衡
打印看起来“对”,其实只是Python做了四舍五入
你看到print(0.1)输出0.1,只是Python默认只显示17位有效数字,并自动舍入到“看起来合理”的形式。真相要用repr()或高精度格式看:
<code>repr(0.1)</code> → '0.1000000000000000055511151231257827021181583404541015625'<br><code>f'{0.1:.20f}'</code> → '0.10000000000000000555'
这种隐式格式化容易让人误以为值是精确的,调试时务必用repr()确认真实值。
真正难的不是理解原理,而是在写业务逻辑时下意识避开浮点陷阱——比如用整数分代替小数元,用时间戳毫秒数代替浮点秒数,这些设计选择比事后修补更可靠。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











