亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 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教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美精品久久一区二区| 久久久久久免费精品| 欧美日韩国产中文精品字幕自在自线| 国产精品自产拍在线观看| 日韩av中文字幕在线| 久久久久久中文字幕| 亚洲午夜精品久久久久久久久久久久| 国产做受高潮69| 91精品91久久久久久| 亚洲精品视频免费| 亚洲人高潮女人毛茸茸| 九九热精品视频国产| 一区二区三区四区精品| 久久精品国产精品亚洲| 欧美视频中文字幕在线| 国产精品色视频| 欧美专区在线观看| 久久偷看各类女兵18女厕嘘嘘| 国产精品久久国产精品99gif| 欧美性少妇18aaaa视频| 日韩av中文字幕在线播放| 亚洲黄色www| 久久久女人电视剧免费播放下载| 亚洲第一区在线| 亚洲免费伊人电影在线观看av| 亚洲在线观看视频网站| 国产精品视频成人| 亚洲国产福利在线| 日韩高清电影好看的电视剧电影| 午夜精品国产精品大乳美女| 亚洲综合中文字幕在线| 久久成人国产精品| 韩国福利视频一区| 成人97在线观看视频| 欧美理论电影在线播放| 国产有码在线一区二区视频| 中文字幕日韩欧美精品在线观看| 欧美日韩精品在线| 欧美大片在线看免费观看| 久久精品视频导航| 日韩高清av一区二区三区| 亚洲国产成人一区| 69av在线播放| 91豆花精品一区| 午夜精品久久久99热福利| 久久五月天色综合| 国产大片精品免费永久看nba| 91九色视频在线| 亚洲第一网站免费视频| 国产在线视频欧美| 国产一区二区三区在线看| 欧美成人亚洲成人| 91午夜理伦私人影院| 高清欧美一区二区三区| 日韩大陆毛片av| 日本成人在线视频网址| 欧美中文字幕在线观看| 美日韩精品免费观看视频| 欧美日韩中文字幕在线| 亚洲精品v欧美精品v日韩精品| 青草热久免费精品视频| 欧美性猛交xxxxx免费看| 亚洲天堂色网站| 久久久亚洲精品视频| 国产人妖伪娘一区91| 亚洲丝袜在线视频| 日韩电视剧免费观看网站| 欧美夜福利tv在线| 亚洲久久久久久久久久久| 综合激情国产一区| 国产精品老牛影院在线观看| 亚洲欧美激情精品一区二区| 欧美有码在线视频| 亚洲国产精品久久精品怡红院| 亚洲精品久久久久久久久久久| 日韩视频在线免费| 国产欧美日韩视频| 91精品久久久久久久久中文字幕| 国产精品一区二区三区毛片淫片| 美女撒尿一区二区三区| 91国在线精品国内播放| 日韩av网址在线观看| 最新69国产成人精品视频免费| 久久国产精品网站| 欧美成人在线网站| 亚洲人成伊人成综合网久久久| 最近免费中文字幕视频2019| 国产成人精品免费视频| 国产精品18久久久久久麻辣| 国产一区二区精品丝袜| 久久国产精品电影| 亚洲福利视频免费观看| 亚洲激情 国产| 国产精品美女免费看| 日韩中文字幕在线视频| 国产亚洲欧洲高清| 国产精品久久久久久网站| 国模私拍一区二区三区| 日韩第一页在线| 日韩激情第一页| 欧美视频中文字幕在线| 亚洲精品日韩久久久| 精品久久久久人成| 国产精品香蕉av| 91爱视频在线| 欧美成人精品一区| 国产在线不卡精品| 国产视频精品免费播放| 亚洲欧美制服中文字幕| 日韩在线播放av| 欧美日韩中文字幕综合视频| 成人午夜在线观看| 久久久最新网址| 波霸ol色综合久久| 国产精品视频自在线| 久久精品国产视频| 少妇高潮久久77777| 亚洲va欧美va在线观看| 欧美精品激情blacked18| 久久国产精品99国产精| 日韩一区二区三区xxxx| 日韩精品在线观看一区| 国产一区二区三区在线免费观看| 亚洲精品白浆高清久久久久久| 国产精品老女人精品视频| 日韩在线观看视频免费| 国产精品久久一区| 欧美视频精品一区| 亚洲国产精品成人精品| 欧美精品www| 这里只有精品视频在线| 久久久久久久亚洲精品| 精品国产一区二区三区久久狼黑人| 久久精品国产视频| 午夜精品一区二区三区av| 韩国三级电影久久久久久| 国产精品视频精品| 欧美日韩国产一区中文午夜| 欧美重口另类videos人妖| 国产精品久久久久久久久久久久久久| 亚洲国产天堂久久国产91| 国产精品久久久一区| 国产精品成人品| 国产69久久精品成人看| 欧美亚洲成人免费| 亚洲国产精品一区二区三区| 91色视频在线观看| 久久精品国产欧美激情| 久久全国免费视频| 日韩女在线观看| 国产在线观看精品一区二区三区| 在线观看视频亚洲| 91免费视频网站| 欧美另类69精品久久久久9999| 亚洲成人网av| 亚洲精选中文字幕| 亚洲综合在线做性| 国产精品一区二区av影院萌芽| 日韩免费在线免费观看| 97视频网站入口| 成人精品一区二区三区电影黑人| 欧美激情一区二区三级高清视频| 亚洲天堂免费观看| 欧美大胆a视频|