浮点数精度陷阱
0.1 + 0.2 ≠ 0.3 的原因和解决方案
- 理解二进制浮点数表示的局限
- 掌握浮点数比较的正确方法
- 了解 decimal 精确十进制
- 知道何时用整数替代浮点数
浮点数精度陷阱
0.1 + 0.2 ≠ 0.3 在几乎所有编程语言中都成立。这不是 Python 的 bug,是 IEEE 754 浮点数标准的本质问题。
问题重现
Python 的 float 是 IEEE 754 双精度浮点数,用 64 位存储:1 位符号 + 11 位指数 + 52 位尾数。能精确表示的十进制小数很少,只有 0.5、0.25、0.125 这类 2 的负幂次可以精确表示。0.1 存储为最接近的二进制近似值,所以有微小误差。
正确比较浮点数
decimal:精确十进制
涉及金钱的计算永远不要用 float!浮点误差累积后会导致账目对不上。用 Decimal(精确十进制)或用整数存储最小单位(分)。例如 19.99 元存为 1999 分,所有计算用整数,显示时再除以 100。这是金融系统的标准做法。
用整数避免浮点问题
0.1 的二进制表示
0.1 在二进制中是无限循环小数:
0.1 + 0.2 == 0.3 的结果是?
金融计算应该用什么类型?
资深工程师加餐
底层原理 · 大厂视角 · 工程经验,点卡片展开
内层函数(或 lambda)捕获的是外层变量本身,而不是定义那一刻的值;循环里定义的多个函数,循环结束后调用往往都拿到最后的值。解决办法是用默认参数 f(x=x) 立即绑定,或用工厂函数包一层。配合 LEGB 作用域顺序(局部→外层→全局→内建)理解,90% 的作用域谜题都能解开。
挑战任务
精确价格计算
用 Decimal 计算三件商品的总价,含8%税,结果精确到分。
课后作业
浮点数安全比较
写一个函数 safe_equal(a, b),用 math.isclose 安全比较两个浮点数。