BigDecimal精度與相等比較的坑

2021-08-28 02:24:04 字數 2647 閱讀 8116

先想一下,建立bigdecimal物件的時候一般是怎麼建立的?

作為乙個數字型別,經常有的操作是比較大小,有一種情況是比較是否相等。用equal方法還是compareto方法?這裡就是乙個大坑

1

//new 傳進去乙個double

2 bigdecimal newzero = new bigdecimal(0.0);

3system.out.println(bigdecimal.zero.equals(newzero));45

//new 傳進去乙個字串

6 bigdecimal stringnewzero = new bigdecimal("0.0");

7system.out.println(bigdecimal.zero.equals(stringnewzero));89

//valueof 傳進去乙個double

10 bigdecimal noscalezero = bigdecimal.valueof(0.0);

11system.out.println(bigdecimal.zero.equals(noscalezero));

1213

//valueof 傳進去乙個double,再手動設定精度為1

14 bigdecimal scalezero = bigdecimal.valueof(0.0).setscale(1);

15 system.out.println(bigdecimal.zero.equals(scalezero));

用於比較的值全都是0,猜一猜上面幾個equals方法返回的結果是什麼?全都是true?no no no...

true

false

false

false

驚不驚喜,意不意外?原因是什麼呢?看一下bigdecimal的equals方法的實現:

1

public

boolean

equals(object x) else

if (xs !=inflated)

19return xs == compactvalfor(this

.intval);

2021

return

this

.inflated().equals(xdec.inflated());

22 }

從前面三個簡單的判斷就可以看出來,debug跟一下就知道是上面equals方法有三個返回false,都是因為精度不同。那麼bigdecimal.zero的精度是多少呢?看下原始碼:

1

//cache of common small bigdecimal values.

2private

static

final bigdecimal zerothroughten =;

1516

17/**

18* the value 0, with a scale of 0.19*

20*

@since

1.521

*/22

public

static

final bigdecimal zero = zerothroughten[0];

bigdecimal.zero值為0,精度為0.

而上面幾種返回false的case,都是因為精度不同。精度不同的原因,則是bigdecimal物件初始化的方式不同,從原始碼上看,前三種初始化的方式都不同。

所以說,bigdecimal比較大小,還是用compareto方法比較靠譜,改為compareto之後,上面四個case返回的結果都是相等:

1 bigdecimal newzero = new bigdecimal(0.0);

2system.out.println(bigdecimal.zero.compareto(newzero));

34 bigdecimal stringnewzero = new bigdecimal("0.0");

5system.out.println(bigdecimal.zero.compareto(stringnewzero));

67 bigdecimal noscalezero = bigdecimal.valueof(0.0);

8system.out.println(bigdecimal.zero.compareto(noscalezero));

910 bigdecimal scalezero = bigdecimal.valueof(0.0).setscale(1);

11 system.out.println(bigdecimal.zero.compareto(scalezero));

輸出結果

000

0

由此聯想到的乙個更大的坑是,如果將bigdecimal的值作為hashmap的key,因為精度的問題,相同的值就可能出現hashcode值不同並且equals方法返回false,導致put和get就很可能會出現相同的值但是訪問了不同的value。

再想一想,小數型別在計算機中本來就不能精確儲存,再把其作為hashmap的key就相當不靠譜了,以後還是少用。

另外需要注意的一點是,寫**調別人寫的方法時,最好是點進去看一下實現。再小再常用的方法,都可能埋著大坑

BigDecimal精度與相等比較的坑

先想一下,建立bigdecimal物件的時候一般是怎麼建立的?作為乙個數字型別,經常有的操作是比較大小,有一種情況是比較是否相等。用equal方法還是compareto方法?這裡就是乙個大坑 1 new 傳進去乙個double 2 bigdecimal newzero new bigdecimal ...

BigDecimal精度與相等比較的坑

先想一下,建立bigdecimal物件的時候一般是怎麼建立的?作為乙個數字型別,經常有的操作是比較大小,有一種情況是比較是否相等。用equal方法還是compareto方法?這裡就是乙個大坑 1 new 傳進去乙個double 2 bigdecimal newzero new bigdecimal ...

BigDecimal 精度問題

在使用bigdecimal過程中,暫時遇到兩個問題,都是精度問題,乙個是精度丟失,乙個是精度顯示問題。bigdecimal建立物件有很多種方式 通過double型別去宣告bigdecimal物件時,就發生精度不准的問題 這個就不建議使用了,可以換種方式去解決這個問題,用string構造器構建物件 設...