应避免用==比较浮点数,因其二进制表示存在舍入误差,导致0.1f+0.2f≠0.3f等逻辑错误,进而引发分支误判、死循环或条件跳过。

在流程控制中用==判断浮点数是否相等,会直接导致分支走错、循环卡死或条件跳过——这不是代码写错了,而是浮点数在计算机里根本存不准。
浮点数本身就不等于“数学上的它”
像 0.1、0.2、0.3 这些常见小数,在二进制下是无限循环小数(类似十进制的 1/3 = 0.333…),而 IEEE 754 标准只能用有限位存储(float 23 位尾数,double 52 位)。系统必须截断或舍入,于是:
-
0.1f + 0.2f实际存的是0.30000001192092896 -
0.3f字面量存的也是近似值,但可能和上面那个“看起来一样、内存不同” - 哪怕只差最后一位比特,
==就返回false
流程控制对“不等”特别敏感
if、while、for 这类结构依赖精确的真假判断,而浮点误差会让逻辑彻底跑偏:
-
if (score == 0.95)→ 模型输出是0.9499999999999999,条件不成立,整条数据被丢弃 -
while (x != 1.0) { x += 0.1; }→x永远加不到精确的1.0,陷入死循环 for (double t = 0.0; t → 最后一次迭代可能跳过 <code>t == 1.0,少执行一次
不同路径让同一数值“变出多个样子”
流程中变量来源越多样,失真风险越高:
- 从 JSON 解析来的
"0.95"→ 走Double.parseDouble()得到 A - 数据库 DECIMAL 字段转 double → 多一次类型转换,得到 B(B ≠ A)
- 代码里直接写的
0.95d→ 编译期固化,得到 C(C 可能又和 A、B 不同) - 三个值数学意义相同,但任意两个做
==都可能失败
更安全的替代做法
不追求“完全相等”,只确保“业务上可接受”:
- 改用容差比较:
Math.abs(a - b) (float)或 <code>(double) - 关键阈值提前标准化:
double rounded = Math.round(confidence * 100.0) / 100.0,再用于判断 - 金额、计数、索引类场景,直接用整数代替:
priceInCents而非priceInDollars - 避免把浮点数当循环变量或终止条件,改用整数计数器驱动逻辑











