<p>Java中浮点数不能用equals()比较,因其按对象语义严格比较值与精度(标度),类型不同或标度不等均返回false;基本类型避免==,因二进制近似导致误差累积;应采用误差阈值法如Math.abs(a - b) < THRESHOLD。</p>
Java 中浮点数不能用 equals() 比较,根本原因在于它不是数值相等判断,而是对象语义的严格比较——既看值,也看精度(即小数位数)。哪怕数学上相等,只要标度不同,equals() 就返回 false。
Float 和 Double 的 equals() 方法内部会先检查类型,再比对数值和标度。例如:
new Float(0.1f).equals(new Double(0.1)) → false(类型不同)new Double(1.0).equals(new Double(1.00)) → true(Double 标度不参与 equals 判断,但这是特例)new BigDecimal("1.0").equals(new BigDecimal("1.00")) → false(标度 1 ≠ 标度 2)float/double 是二进制近似表示,0.1 在内存中本就无法精确存储。运算后误差累积,直接 == 极易失败:
0.1f + 0.2f == 0.3f → false
1.0 / 10 == 0.1d → false(float 升级为 double 后,二进制近似值已不同)普通精度容忍场景:用误差阈值
立即学习“Java免费学习笔记(深入)”;
THRESHOLD,比如 1e-6(float)或 1e-10(double)Math.abs(a - b)
金融/高精度场景:用 BigDecimal
new BigDecimal("0.1"),禁用 new BigDecimal(0.1)
compareTo():a.compareTo(b) == 0(只比数值,忽略标度)add、subtract、multiply、divide(除法务必指定 scale 和 RoundingMode)equals() 在 BigDecimal 中是“值 + 标度”双重校验。这意味着:
new BigDecimal("1.0").equals(new BigDecimal("1.00")) 是 false
new BigDecimal("1.0").compareTo(new BigDecimal("1.00")) == 0 是 true
someBigDecimal.equals("1.0") 总是 false(类型不匹配,不解析字符串)