发布于2026-07-11 阅读(0)
扫一扫,手机访问
浮点数比较,直接用 == 大概率会踩坑。比如经典的 0.1 + 0.2 == 0.3 返回 False,原因很简单:0.1 和 0.2 这类十进制小数在二进制中是无限循环小数,IEEE 754 双精度只能截断存储,导致 0.1 + 0.2 实际存的是 0.30000000000000004,而 0.3 是另一个近似值——两者内存表示不同,== 自然不成立。所以,math.isclose() 才是更靠谱的选择。

原理很直接:0.1、0.2 在二进制里是无限循环小数,IEEE 754 双精度只能存 52 位尾数,不得不截断。所以 0.1 + 0.2 实际存储的是 0.30000000000000004,而 0.3 存的是另一个近似值——内存表示不同,== 自然返回 False。这可不是 Python 的 bug,Ja va、C、Ja vaScript 全都一个样。
直接用 math.isclose(a, b) 要比自己手写 abs(a - b) < epsilon 稳妥得多,因为它同时考虑了相对误差和绝对误差。具体参数怎么设?
rel_tol=1e-09(默认)适合数量级相近的数,比如 123.456 和 123.457 这种。abs_tol=1e-09(默认)必须显式设定,尤其当其中一个数接近 0 时——否则 rel_tol 在分母趋近 0 会失效,比如判断 result 是否收敛到 0.0。math.isclose:它底层仍是浮点运算,建议先转整数或 Decimal 再比较。因为 Decimal 是十进制精确算术,不经过二进制转换。几个关键点需要注意:
Decimal('0.1') —— 这样字面量的精度被完整保留。Decimal(0.1) —— 此时 0.1 已经是二进制近似值,再包装也没用。getcontext().prec 控制的是有效数字位数,不是小数位数;多线程中要用 localcontext() 隔离,避免互相污染。不是所有地方都要上 Decimal 或容差判断。比如:
1e-5 级误差不敏感。==。真正容易被忽略的,是那些“看起来安全”的边界情况:比如用 while x != 1.0: 控制循环,一旦 x 因累加误差变成 0.9999999999999999,就卡死;或者把 float 直接塞进字典键,导致重复插入。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8