Bigdecimal類型如何比較值相等


Bigdecimal是一個對象,不是基本的數據類型,因此沒有Bigdecimal數據類型比較方法這么一說。這里總結一下Bigdecimal對象如何比較值相等。

 

1、Bigdecimal類型不能直接使用 "=="

 

可以看到,由於是包裝類型,因此建議使用equals 進行比較

但是使用equals進行比較就一定對嗎?

 

2、BigDecimal類型使用equals比較中的坑

測試代碼如下:

 1 public class BigDecimalTest {
 2     void test01(){
 3         BigDecimal num1 = BigDecimal.valueOf(0.00);
 4         System.out.println(num1.equals(0));     //false
 5         System.out.println(num1.equals("0"));   //false
 6     }
 7 
 8     void test02(){
 9         BigDecimal num1 = new BigDecimal("0.00");
10         System.out.println(num1.equals(0));     //false
11         System.out.println(num1.equals("0"));   //false
12     }
13 
14     void test03(){
15         BigDecimal a = new BigDecimal(0.00);
16         BigDecimal b = new BigDecimal(0);
17         System.out.println(a.equals(b));    //true         
18     }
19 
20     void test04(){
21         BigDecimal a = new BigDecimal("0.00");
22         BigDecimal b = new BigDecimal("0");
23         System.out.println(a.equals(b));    //false
24     }
25 
26     public static void main(String[] args) {
27         BigDecimalTest t = new BigDecimalTest();
28         System.out.println("test01():________________");
29         t.test01();
30         System.out.println("test02():________________");
31         t.test02();
32         System.out.println("test03():________________");
33         t.test03();
34         System.out.println("test04():________________");
35         t.test04();
36     }
37 }

 

我們可以看到,我們使用不同的方法構造的BigDecimal類型的數據,但是結果並不是相等的

傳入字符串的構造器時等同於數據庫查詢出來的值

 

原因是什么呢?

我們來看一下傳如String類型時的構造器:

1 public BigDecimal(String val) {
2     this(val.toCharArray(), 0, val.length());
3 }

該構造器的注釋:

 

可以看出,“0”傳入構造器得到的是0且沒有小數位,“0.00”傳入構造器得到的是0.00,含有2位小數

再看看equals方法:

 1     public boolean equals(Object x) {
 2         //比較對象是否是BigDecimal的數據類型,如果不是直接返回false
 3         if (!(x instanceof BigDecimal))
 4             return false;
 5         BigDecimal xDec = (BigDecimal) x;
 6         if (x == this)
 7             return true;
 8         //比較BigDecimalde scale值是否相等
 9         /* scale 是BigDecimal 的標度。如果為零或正數,則標度是小數點后的位數。
10          如果為負數,則將該數的非標度值乘以 10 的負 scale 次冪。例如,-3 標度是指非標度值乘以 1000。*/
11         if (scale != xDec.scale)
12             return false;
13         long s = this.intCompact;
14         long xs = xDec.intCompact;
15         // 返回給定的xDec.intVal的compact 值,如果太大,則返回INFLATED。
16         // 返回給定的this.intVal的compact 值,如果太大,則返回INFLATED。
17         if (s != INFLATED) {
18             if (xs == INFLATED)
19                 xs = compactValFor(xDec.intVal);
20             return xs == s;
21         } else if (xs != INFLATED)
22             return xs == compactValFor(this.intVal);
23 
24         return this.inflated().equals(xDec.inflated());
25     }

該方法的注釋為:

 

可以清晰看到equals方法比較了小數位數 -----> if (scale != xDec.scale) return false; 

到這里可以理解上面test04()比較結果為什么是false了

 

而使用new Decimal(double val),是將雙精度轉換為BigDecimal,BigDecimal是雙精度二進制浮點值的精確十進制表示形式。返回的BigDecimal的小數位數是最小的值,因此(10scale×val)是一個整數。

官方注釋說這個構造函數的結果可能有些不可預測。不建議使用

 

3、BigDecimal類型應該使用compareTo()方法進行比較

compareTo()方法:
* 將此 BigDecimal 與指定的 BigDecimal 比較。
*值相等但具有不同標度的兩個 BigDecimal 對象(如,2.0 和 2.00)被認為是相等的。
* 小於、等於或大於 時,返回 -1、0 或 1

public class BigDecimalTest {
    void test05(){
        BigDecimal num1 = new BigDecimal("0");
        BigDecimal num2 = new BigDecimal("0.00");
        System.out.println(num2.compareTo(num1)); // 0
    }

    public static void main(String[] args) {
        BigDecimalTest t = new BigDecimalTest();
        t.test05();
    }
}

對於compareTo() 方法:

 1     public int compareTo(BigDecimal val) {
 2         // Quick path for equal scale and non-inflated case.
 3         if (scale == val.scale) {
 4             long xs = intCompact;
 5             long ys = val.intCompact;
 6             if (xs != INFLATED && ys != INFLATED)
 7                 return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
 8         }
 9         int xsign = this.signum();
10         int ysign = val.signum();
11         if (xsign != ysign)
12             return (xsign > ysign) ? 1 : -1;
13         if (xsign == 0)
14             return 0;
15         int cmp = compareMagnitude(val);
16         return (xsign > 0) ? cmp : -cmp;
17     }

可以看到,分了2種情況,一種是含有小數位相同,另一種時不相同的情況。所以不管2個數的小數位是否相同,都會進行值的比較。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM