国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java中BigDecimal精度和相等比較的坑

Java中BigDecimal精度和相等比較的坑

2021-05-31 13:57八行書 Java教程

BigDecimal是一種精確的數字類,一般用于高精度的開發領域中,例如銀行。下面這篇文章主要給大家介紹了關于Java中BigDecimal精度和相等比較的坑的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下

為什么要有bigdecimal ,他是干什么的

float和double類型的主要設計目標是為了科學計算和工程計算。他們執行二進制浮點運算,這是為了在廣域數值范圍上提供較為精確的快速近似計算而精心設計的。然而,它們沒有提供完全精確的結果,所以不應該被用于要求精確結果的場合。但是,商業計算往往要求結果精確,這時候就要使用bigdecimal啦。

什么是bigdecimal

bigdecimal 由任意精度的整數非標度值 和32 位的整數標度 (scale) 組成。如果為零或正數,則標度是小數點后的位數。如果為負數,則將該數的非標度值乘以 10 的負scale 次冪。因此,bigdecimal表示的數值是(unscaledvalue × 10-scale)。

本文將給大家詳細介紹關于java中bigdecimal精度和相等比較的坑,下面話不多說了,來一起看看詳細的介紹吧

先想一下,創建bigdecimal對象的時候一般是怎么創建的?

  • new一個,傳進去值
  • bigdecimal.valueof方法,傳進去值 

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//new 傳進去一個double
bigdecimal newzero = new bigdecimal(0.0);
system.out.println(bigdecimal.zero.equals(newzero));
 
//new 傳進去一個字符串
bigdecimal stringnewzero = new bigdecimal("0.0");
system.out.println(bigdecimal.zero.equals(stringnewzero));
 
//valueof 傳進去一個double
bigdecimal noscalezero = bigdecimal.valueof(0.0);
system.out.println(bigdecimal.zero.equals(noscalezero));
 
//valueof 傳進去一個double,再手動設置精度為1
bigdecimal scalezero = bigdecimal.valueof(0.0).setscale(1);
system.out.println(bigdecimal.zero.equals(scalezero));

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

true
false
false
false

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public boolean equals(object x) {
 //類型不同,直接返回false
 if (!(x instanceof bigdecimal))
  return false;
 bigdecimal xdec = (bigdecimal) x;
 //同一個對象,直接返回true
 if (x == this)
  return true;
 //精度不同,直接返回false!!
 if (scale != xdec.scale)
  return false;
 long s = this.intcompact;
 long xs = xdec.intcompact;
 if (s != inflated) {
  if (xs == inflated)
   xs = compactvalfor(xdec.intval);
  return xs == s;
 } else if (xs != inflated)
  return xs == compactvalfor(this.intval);
 
 return this.inflated().equals(xdec.inflated());
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// cache of common small bigdecimal values.
private static final bigdecimal zerothroughten[] = {
 new bigdecimal(biginteger.zero,  0, 0, 1),
 new bigdecimal(biginteger.one,  1, 0, 1),
 new bigdecimal(biginteger.valueof(2), 2, 0, 1),
 new bigdecimal(biginteger.valueof(3), 3, 0, 1),
 new bigdecimal(biginteger.valueof(4), 4, 0, 1),
 new bigdecimal(biginteger.valueof(5), 5, 0, 1),
 new bigdecimal(biginteger.valueof(6), 6, 0, 1),
 new bigdecimal(biginteger.valueof(7), 7, 0, 1),
 new bigdecimal(biginteger.valueof(8), 8, 0, 1),
 new bigdecimal(biginteger.valueof(9), 9, 0, 1),
 new bigdecimal(biginteger.ten,  10, 0, 2),
};
 
 
/**
 * the value 0, with a scale of 0.
 *
 * @since 1.5
 */
public static final bigdecimal zero = zerothroughten[0];

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
bigdecimal newzero = new bigdecimal(0.0);
system.out.println(bigdecimal.zero.compareto(newzero));
 
bigdecimal stringnewzero = new bigdecimal("0.0");
system.out.println(bigdecimal.zero.compareto(stringnewzero));
 
bigdecimal noscalezero = bigdecimal.valueof(0.0);
system.out.println(bigdecimal.zero.compareto(noscalezero));
 
bigdecimal scalezero = bigdecimal.valueof(0.0).setscale(1);
system.out.println(bigdecimal.zero.compareto(scalezero));

輸出結果

0
0
0
0

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

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

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://www.cnblogs.com/z941030/p/9639717.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日本在线免费看 | 一级毛片免费视频 | 欧美午夜寂寞影院 | 色视频免费在线 | 国产精品久久久久精 | 欧美日韩中| 精品国偷自产国产一区 | 久草青青| 亚洲国产精品久久久久婷婷老年 | 久久精品国产亚洲 | 日韩精品三区 | 特级毛片在线 | 成人av网站在线观看 | 日韩色区 | 日韩精品中文字幕在线 | 国产欧美日韩一区二区三区 | 国产成人精品久久二区二区91 | 午夜av电影 | 一区二区在线不卡 | www.av在线.com| 精品久久一区二区三区 | 极品美女销魂一区二区三区 | 久久精品亚洲一区二区 | 91正在播放| 久久亚 | 色婷婷精品久久二区二区蜜臂av | 精品综合| 99久久久国产精品 | 国产精品无码久久久久 | 亚洲一区视频 | 久久国产综合 | 国产精品一二区 | 偷拍自拍亚洲欧美 | 欧洲亚洲视频 | 国产一区二 | 天天操网址 | 久久久久久久久久久免费av | 毛片在线视频 | 久久av一区二区三区 | 日韩中文字幕 | 久久久久亚洲 |