先想一下,建立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...
truefalse
false
false
驚不驚喜,意不意外?原因是什麼呢?看一下bigdecimal的equals方法的實現:
1public
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));
輸出結果
0000
由此聯想到的乙個更大的坑是,如果將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構造器構建物件 設...