麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發 > Java > 正文

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

2024-07-14 08:42:21
字體:
來源:轉載
供稿:網友

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

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

什么是BigDecimal

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

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

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

  • new一個,傳進去值
  • BigDecimal.valueOf方法,傳進去值 

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

//new 傳進去一個doubleBigDecimal 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 傳進去一個doubleBigDecimal noScaleZero = BigDecimal.valueOf(0.0);System.out.println(BigDecimal.ZERO.equals(noScaleZero)); //valueOf 傳進去一個double,再手動設置精度為1BigDecimal 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方法的實現:

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的精度是多少呢?看下源碼:

// 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返回的結果都是相等:

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就相當不靠譜了,以后還是少用。

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

總結

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


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 亚洲小视频| 青草视频在线观看视频 | 日韩中文一区 | 国产一区网址 | chinesehdxxxx无套 久久另类视频 | 久草在线高清视频 | 欧美亚州 | 色综合视频 | 九一免费在线观看 | 日本在线播放一区二区三区 | 国产精品视频二区不卡 | 成人在线视频免费看 | 久久伊人国产精品 | 久久久久久久久免费 | 中文字幕在线观看精品 | 亚洲特黄 | asian gaysex| 91美女福利视频 | 欧美性黄 | 国产羞羞视频 | 中国免费一级毛片 | 午夜在线视频一区二区三区 | 日本黄色大片免费 | 国产精品视频一区二区三区四区国 | 国产精品免费观在线 | 中文字幕在线观看视频www | 成人免费网站在线观看视频 | 免费午夜视频在线观看 | 男男羞羞视频网站国产 | 鲁丝一区二区二区四区 | 成人福利在线视频 | 久久99精品久久久久久秒播蜜臀 | 国产日韩在线观看视频 | 久草在线最新 | 久国产精品视频 | 欧美成人免费电影 | 欧美精品免费一区二区三区 | 日韩黄色精品 | 九九热精品在线 | 91午夜在线观看 | 午夜在线成人 |