应使用误差容忍法比较浮点数:取绝对差小于阈值(如1e-9),大数场景结合相对误差,金融场景改用整数或十进制运算,避免浮点循环和索引依赖。

直接用 == 判定两个浮点数是否“相等”,几乎总会出错。这不是代码写错了,而是因为 0.1、0.2、0.3 这类常见小数在二进制中无法精确表示,计算结果天然带微小误差——比如 0.1 + 0.2 实际存的是 0.30000000000000004,和 0.3 的内存值不同,== 自然返回 false。要避免逻辑失效,关键是把“是否完全一样”的思维,换成“差得够不够小”。
用误差容忍法替代 == 判断
这是最常用也最有效的做法:引入一个极小阈值(epsilon),检查两数之差的绝对值是否小于它。
- 对
double类型,常用1e-9;对float,可用1e-6 - 别直接抄
DBL_EPSILON或Float.MIN_VALUE——它们是 1.0 附近的最小可分辨增量,太小,不适用于通用比较 - 写法示例(Java):
Math.abs(a - b)
(C/C++ 用fabs(a - b) ;Python 用abs(a - b) )
大数或跨量级场景下加相对误差
纯绝对误差在数值很大(如 1e6)或接近 0 时容易失灵。例如比较 1000000.001 和 1000000.002,绝对差是 0.001,但若 epsilon 只设 1e-9,就永远不成立。
- 推荐组合判断:
abs(a - b) - C++20 的
std::is_close(a, b, rtol=1e-9, atol=1e-12)就是这种思路,已内置 NaN/Inf 保护 - 自己实现时,务必先单独检查
Double.isNaN(a) || Double.isNaN(b),否则abs(NaN - x)仍是NaN,比较失效
金融、金额类场景彻底避开浮点数
如果业务要求零误差(比如账户余额、支付扣款),浮点类型本身就不该出现。此时不是调 epsilon,而是换数据表达方式。
- PHP 用 BCMath:
bcscale(2); $sum = bcadd('19.99', '5.01');,全程十进制字符串运算 - C/C++/Java 用整数单位:金额统一存为“分”,全部用
int或long运算,显示时再除以 100 - 数据库字段必须用
DECIMAL(10,2),而非FLOAT或DOUBLE
警惕循环条件和索引里的浮点依赖
这类写法极易引发死循环或越界:
- 错误:
for (double x = 0.0; x != 1.0; x += 0.1)——x永远达不到精确的1.0 - 正确:改用整数计数器:
for (int i = 0; i - 数组索引、状态切换条件中,也应避免用浮点值做
==或!=判断,优先改用、>=等有序比较










