最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
为什么Python中的实数比较不能直接用等于号而要定义阈值?
时间:2026-07-12 09:25:02 编辑:袖梨 来源:一聚教程网
浮点数 == 比较总返回 False,因 0.1、0.2 在二进制中为无限循环小数,IEEE 754 双精度截断导致 0.1 + 0.2 实际为 0.30000000000000004,与 0.3 的近似值不同;math.isclose() 更可靠。
浮点数 == 比较为什么总返回 False
因为 0.1、0.2 这类十进制小数在二进制中是无限循环小数,IEEE 754 双精度只能存 52 位尾数,必须截断——所以 0.1 + 0.2 实际存储的是 0.30000000000000004,而 0.3 存的是另一个近似值,两者内存表示不同,== 自然返回 False。这不是 Python 的 bug,Java、C、JavaScript 全都一样。
math.isclose() 的 rel_tol 和 abs_tol 怎么设
直接用 math.isclose(a, b) 比手写 abs(a - b) 更稳妥,因为它同时考虑相对误差和绝对误差:
-
rel_tol=1e-09(默认)适合比较数量级相近的数,比如123.456和123.457 -
abs_tol=1e-09(默认)必须显式设,尤其当其中一个数接近 0 时——否则rel_tol在分母趋近 0 会失效,比如判断result是否收敛到0.0 - 金融场景慎用
math.isclose:它仍是浮点运算,建议先转整数或Decimal再比
Decimal('0.1') + Decimal('0.2') == Decimal('0.3') 为什么能成立
因为 Decimal 是十进制精确算术,不经过二进制转换:
- ✅ 必须用字符串初始化:
Decimal('0.1')—— 字面量精度被完整保留 - ❌ 绝对不能用 float 初始化:
Decimal(0.1)—— 此时0.1已经是二进制近似值,再包装也没用 - ⚠️
getcontext().prec控制的是有效数字位数,不是小数位数;多线程中要用localcontext()隔离,避免互相污染
哪些场景其实可以放心用 float ==
不是所有地方都要上 Decimal 或容差判断:
立即学习“Python免费学习笔记(深入)”;
- 图形渲染坐标、归一化向量长度、机器学习训练中的梯度更新:硬件加速依赖 float,人眼/模型对
1e-5级误差不敏感 - GPS 坐标、加速度计原始读数:设备自身误差(米级、百分之一 g)远大于浮点表示误差
- 但凡涉及金额、阈值触发、单元测试断言、收敛判断——一律禁用
==
真正容易被忽略的,是那些“看起来安全”的边界情况:比如用 while x != 1.0: 控制循环,一旦 x 因累加误差变成 0.9999999999999999,就卡死;或者把 float 直接塞进字典键,导致重复插入。
相关文章
- 迷你世界炎狱魔龙如何获得 炎狱魔龙技能图鉴 07-20
- 迷你世界厨房修建攻略 迷你世界厨房搭建方法 07-20
- 洛克王国世界s3赛季什么时候开始 07-20
- 绝区零希格莉德立绘合集 希格莉德值得抽吗 07-20
- 《明日方舟:终末地》塔晶系统介绍 07-20
- 金铲铲之战s18索拉卡羁绊技能分享 07-20