回答:
因为BigDecimal的equals方法和compareTo并不一样,equals方法会比较两部分内容,分别是值和精度,而对于0.1和0.10这两个数字,他们的值虽然一样,但是精度是不一样的,所以在使用equals比较的时候会返回false,即会比较值和小数点位是否相等。
扩展
BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种java.math包中提供的一种可以用来进行精确运算的类型。
很多人都知道,在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecimal。
所以,很多支付、电商、金融等业务中,BigDecimal的使用非常频繁。而且不得不说这是一个非常好用的类,其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的。
除了需要用BigDecimal表示数字和进行数字运算以外,代码中还经常需要对于数字进行相等判断。
关于这个知识点,在最新版的《阿里巴巴Java开发手册》中也有说明:
10.【强制】如上所示BigDecimal的等值比较应使用compareTo()方法,而不是equals()方法。说明:equals方法会比较值和精度(1.0与1.00返回结果为false),而compareTo则会忽略精度。
BigDecimal的比较
上代码
if(bigDecimal == bigDecimal1){
//两个数相等
}
上面存在着代码的低级错误,因为BigDecimal是对象,所以不能用==来判断两个数字的值是否相等。
但是再看一下以下的代码
BigDecimal bigDecimal = new BigDecimal(1);
BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println(bigDecimal.equals(bigDecimal1));
BigDecimal bigDecimal2 = new BigDecimal(1);
BigDecimal bigDecimal3 = new BigDecimal(1.0);
System.out.println(bigDecimal2.equals(bigDecimal3));
BigDecimal bigDecimal4 = new BigDecimal("1");
BigDecimal bigDecimal5 = new BigDecimal("1.0");
System.out.println(bigDecimal4.equals(bigDecimal5));
以上代码输出结果位
true
true
false
这里就涉及到BigDecimal中equals原理了,它会比较值和精度两部分,所以第一个和第三个为true和false, 但是为什么第二个精度不一样会是true呢?
这里又涉及到BigDecimal的标度问题了,这个问题其实比较复杂,这里简单写下:
首先, BigDecimal一共有四种构造方法:
BigDecimal(int)
BigDecimal(double)
BigDecimal(long)
BigDecimal(String)
以上四个方法创建出来的BigDecimal的精度(标度)是不同的。
为什么标度不同
BigDecimal(int) BigDecimal(long)
BigDecimal(int) BigDecimal(long) 因为都是整数,所以标度判定为0
public BigDecimal(int val){
this.intCompact = val;
this.scale = 0;
this.intval null;
}
public BigDecimal(long val){
this.intCompact = val;
this.intval = (val == INFLATED)?INFLATED_BIGINT:null;
this.scale = 0;
}
BigDecimal(double)
而对于BigDecimal(double),当我们使用new BigDecimal(O.1)创建一个BigDecimal的时候,其实创建出来的值并不是整好等于0.1的,而是
0.1000000000000000055511151231257827021181583404541015625。这是因为double自身表示的只是一个近似值。
那么,无论我们使用new BigDecimall(O.1)还是new BigDecimal(O.1O)定义,他的近似值都是
0.1000000000000000055511151231257827021181583404541015625这个,那么他的标度就是这个数字的位数,即55。
其他的浮点数也同样的道理。对于new BigDecimal(1.0)这样的形式来说,因为他本质上也是个整数,所以他创建出来的数字的标度就是0。
所以,因为BigDecimal((1.O)和BigDecimal((1.00)的标度是一样的,所以在使用equals方法比较的时候,得到的结果就是true。
BigDecimal(String)
而对于BigDecimal(String),当我们使用new BigDecimal("O.1”)创建一个BigDecimal的时候,其实创建出来的值正好就是等于0.1的。那么他的标度也就是1。
如果使用new BigDecimal('0.10000”),那么创建出来的数就是0.10000,标度也就是5。
所以,因为BigDecimal(”1.0”)和BigDecimal(”1.00”)的标度不一样,所以在使用equals方法比较的时候,得到的结果就是false。
如何比较BigDecimal
前面,我们解释了BigDecimal的equals方法,其实不只是会比较数字的值,还会对其标度进行比较。所以,当我们使用equals方法判断判断两个数是否相等的时候,是极其严格的。
那么,如果我们只想判断两个BigDecimali的值是否相等,那么该如何判断呢?
BigDecimal中提供了compareTo方法,这个方法就可以只比较两个数字的值,如果两个数相等,则返回0.