BigDecimal对象比较时的注意事项
!NOTE
在涉及到价钱和需要保证高精度的项目中我们往往使用BigDecimal对象来存储值,而在对象在进行比较时有一些地方需要注意(博主也是替大家踩了坑了🥲)
我们先来看下面这几行代码,思考他们的输出:
java
@Test
public void test() {
System.out.println(new BigDecimal(1).equals(new BigDecimal(1.00000)));
System.out.println(new BigDecimal(1).equals(new BigDecimal("1.00000000")));
System.out.println(new BigDecimal(1).compareTo(new BigDecimal("1.00000000000000000000")));
}
结果可能非你所料:
bash
true
false
0
为什么会这样呢?我们来依个分析:
java
new BigDecimal(1).equals(new BigDecimal(1.00000)) //true
对于上面的代码
-
new BigDecimal(1)
- 从int创建,值为1,精度(scale)=0 -
new BigDecimal(1.00000)
- 从double创建,double值1.00000在二进制浮点数中就是1.0 -
问题所在:从double创建:可能丢失精度信息,结果不可预测
java
System.out.println(new BigDecimal(1).equals(new BigDecimal("1.00000000"))); //false
-
new BigDecimal(1)
- 从int创建,值为1,精度(scale)=0 -
new BigDecimal("1.00000000")
- 从字符串创建,值为1,精度(scale)=8 -
问题所在:equals严格比较精度和数值,如果你需要考虑精度的话,可以考虑
java
System.out.println(new BigDecimal(1).compareTo(new BigDecimal("1.00000000000000000000"))); // 0
new BigDecimal(1)
- 值为1,精度=0new BigDecimal("1.00000000000000000000")
- 值为1,精度=20- compareTo只比较数值大小,不比较精度
总结
- 从double创建:可能丢失精度信息,结果不可预测
- 从字符串创建:完全保留精度信息
- equals():严格比较值和精度
- compareTo():只比较数值大小,推荐用于数值比较
所以在实际开发中,对于BigDecimal的数值比较应该使用compareTo() == 0
而不是equals()
(血淋淋的教训😓)。