java浮点数不能用==比较,应使用容差法(如math.abs(a-b)

Java 中浮点数(float 和 double)不能直接用 == 判断相等,这是由 IEEE 754 二进制表示的固有缺陷决定的——像 0.1、0.2 这类十进制小数在二进制中是无限循环小数,存储时必然被截断或舍入,导致计算结果存在微小误差。
用容差(epsilon)代替精确相等
最常用、最轻量的解法是定义一个极小的误差阈值(如 1e-6 或 1e-15),判断两数之差的绝对值是否小于此阈值:
Math.abs(a - b) :适用于 <code>float级别精度需求Math.abs(a - b) :适用于 <code>double级别,但注意不要盲目设太小,可能因计算路径不同引入额外误差- 避免硬写魔法数字,建议声明为
final double EPSILON = 1e-10;,便于统一维护和理解业务容忍度
优先使用 BigDecimal 处理关键场景
当涉及金额、计费、科学测量等**必须精确**的业务逻辑时,应彻底放弃 float/double,改用 BigDecimal:
- 构造时务必用字符串,如
new BigDecimal("0.1");绝不用new BigDecimal(0.1)(会把double的误差原样带入) - 比较用
compareTo()方法(返回 -1/0/1),而不是equals()(后者会比较标度,"2"和"2.0"不等) - 除法必须指定精度和舍入模式,例如
a.divide(b, 2, RoundingMode.HALF_UP)
警惕隐式类型转换和包装类陷阱
类型混用会放大精度问题,且容易被忽略:
-
float f = 0.1f;与double d = 0.1;比较时,f == d几乎总为false,因为两者二进制近似值不同 -
Float和Double包装类的equals()方法内部仍基于原始值比较,同样不解决精度问题 - 避免在集合(如
HashSet、HashMap)中用浮点数作 key,尤其要注意0.0和-0.0在内存中不同但数值相等,可能导致重复插入或查找失败
需要显示或调试时,格式化不等于修复精度
用 DecimalFormat 或 String.format("%.2f", x) 只改变输出外观,底层值仍是近似值。若后续还要参与计算,格式化后的字符串需重新转成 BigDecimal 才可靠:
- 错误做法:
double price = 19.99; String s = String.format("%.2f", price); double again = Double.parseDouble(s);—— 仍可能带回误差 - 正确链路:原始数据 →
BigDecimal计算 →setScale(2, HALF_UP)→toString()显示
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











