最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2018年09月13日 14:51:38   作者:八行書  
BigDecimal是一種精確的數(shù)字類,一般用于高精度的開發(fā)領(lǐng)域中,例如銀行。下面這篇文章主要給大家介紹了關(guān)于Java中BigDecimal精度和相等比較的坑的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

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

float和double類型的主要設(shè)計(jì)目標(biāo)是為了科學(xué)計(jì)算和工程計(jì)算。他們執(zhí)行二進(jìn)制浮點(diǎn)運(yùn)算,這是為了在廣域數(shù)值范圍上提供較為精確的快速近似計(jì)算而精心設(shè)計(jì)的。然而,它們沒有提供完全精確的結(jié)果,所以不應(yīng)該被用于要求精確結(jié)果的場(chǎng)合。但是,商業(yè)計(jì)算往往要求結(jié)果精確,這時(shí)候就要使用BigDecimal啦。

什么是BigDecimal

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

本文將給大家詳細(xì)介紹關(guān)于Java中BigDecimal精度和相等比較的坑,下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧

先想一下,創(chuàng)建BigDecimal對(duì)象的時(shí)候一般是怎么創(chuàng)建的?

  • new一個(gè),傳進(jìn)去值
  • BigDecimal.valueOf方法,傳進(jìn)去值 

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

//new 傳進(jìn)去一個(gè)double
BigDecimal newZero = new BigDecimal(0.0);
System.out.println(BigDecimal.ZERO.equals(newZero));
 
//new 傳進(jìn)去一個(gè)字符串
BigDecimal stringNewZero = new BigDecimal("0.0");
System.out.println(BigDecimal.ZERO.equals(stringNewZero));
 
//valueOf 傳進(jìn)去一個(gè)double
BigDecimal noScaleZero = BigDecimal.valueOf(0.0);
System.out.println(BigDecimal.ZERO.equals(noScaleZero));
 
//valueOf 傳進(jìn)去一個(gè)double,再手動(dòng)設(shè)置精度為1
BigDecimal scaleZero = BigDecimal.valueOf(0.0).setScale(1);
System.out.println(BigDecimal.ZERO.equals(scaleZero));

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

true
false
false
false

驚不驚喜,意不意外?原因是什么呢?看一下BigDecimal的equals方法的實(shí)現(xiàn):

public boolean equals(Object x) {
 //類型不同,直接返回false
 if (!(x instanceof BigDecimal))
  return false;
 BigDecimal xDec = (BigDecimal) x;
 //同一個(gè)對(duì)象,直接返回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());
}

從前面三個(gè)簡(jiǎn)單的判斷就可以看出來(lái),debug跟一下就知道是上面equals方法有三個(gè)返回false,都是因?yàn)榫炔煌?。那?code>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,都是因?yàn)榫炔煌>炔煌脑?,則是BigDecimal對(duì)象初始化的方式不同,從源碼上看,前三種初始化的方式都不同。

所以說(shuō),BigDecimal比較大小,還是用compareTo方法比較靠譜,改為compareTo之后,上面四個(gè)case返回的結(jié)果都是相等:

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));

輸出結(jié)果

0
0
0
0

由此聯(lián)想到的一個(gè)更大的坑是,如果將BigDecimal的值作為HashMap的key,因?yàn)榫鹊膯栴},相同的值就可能出現(xiàn)hashCode值不同并且equals方法返回false,導(dǎo)致put和get就很可能會(huì)出現(xiàn)相同的值但是存取了不同的value。

再想一想,小數(shù)類型在計(jì)算機(jī)中本來(lái)就不能精確存儲(chǔ),再把其作為HashMap的key就相當(dāng)不靠譜了,以后還是少用。

另外需要注意的一點(diǎn)是,寫代碼調(diào)別人寫的方法時(shí),最好是點(diǎn)進(jìn)去看一下實(shí)現(xiàn)。再小再常用的方法,都可能埋著大坑

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Java實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲?附完整源碼

    Java實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲?附完整源碼

    這篇文章主要介紹了Java實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲,本文給大家分享完整源代碼和效果圖展示,對(duì)java飛機(jī)大戰(zhàn)游戲?qū)崿F(xiàn)代碼感興趣的朋友一起看看吧
    2022-05-05
  • JAVA錯(cuò)誤:'無(wú)效目標(biāo)發(fā)行版?17'的解決方案

    JAVA錯(cuò)誤:'無(wú)效目標(biāo)發(fā)行版?17'的解決方案

    這篇文章主要給大家介紹了關(guān)于JAVA錯(cuò)誤:'無(wú)效目標(biāo)發(fā)行版?17'的解決方案,文中通過圖文介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或使用java具有一的的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-09-09
  • Hadoop運(yùn)行時(shí)遇到j(luò)ava.io.FileNotFoundException錯(cuò)誤的解決方法

    Hadoop運(yùn)行時(shí)遇到j(luò)ava.io.FileNotFoundException錯(cuò)誤的解決方法

    今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Hadoop運(yùn)行時(shí)遇到j(luò)ava.io.FileNotFoundException錯(cuò)誤展開,文中有非常詳細(xì)的解決方法,需要的朋友可以參考下
    2021-06-06
  • Spring Cache和EhCache實(shí)現(xiàn)緩存管理方式

    Spring Cache和EhCache實(shí)現(xiàn)緩存管理方式

    這篇文章主要介紹了Spring Cache和EhCache實(shí)現(xiàn)緩存管理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Spring中HandlerMethod類源碼詳細(xì)解析

    Spring中HandlerMethod類源碼詳細(xì)解析

    這篇文章主要介紹了Spring中HandlerMethod類源碼詳細(xì)解析,HandlerMethod類用于封裝控制器方法信息,包含類信息、方法Method對(duì)象、參數(shù)、注解等信息,具體的接口請(qǐng)求是可以根據(jù)封裝的信息調(diào)用具體的方法來(lái)執(zhí)行業(yè)務(wù)邏輯,需要的朋友可以參考下
    2023-11-11
  • Javafx簡(jiǎn)單實(shí)現(xiàn)【我的電腦資源管理器】效果

    Javafx簡(jiǎn)單實(shí)現(xiàn)【我的電腦資源管理器】效果

    這篇文章主要介紹了Javafx簡(jiǎn)單實(shí)現(xiàn)【我的電腦資源管理器】效果,涉及Javafx操作系統(tǒng)文件模擬資源管理器的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • Spring Boot的properties配置文件讀取

    Spring Boot的properties配置文件讀取

    這篇文章主要介紹了Spring Boot的properties配置文件讀取,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2017-06-06
  • java網(wǎng)上圖書商城(2)Category模塊

    java網(wǎng)上圖書商城(2)Category模塊

    這篇文章主要介紹了java網(wǎng)上圖書商城,Category模塊,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 關(guān)于報(bào)錯(cuò)IDEA Terminated with exit code 1的解決方法

    關(guān)于報(bào)錯(cuò)IDEA Terminated with exit code 

    如果在IDEA構(gòu)建項(xiàng)目時(shí)遇到下面這樣的報(bào)錯(cuò)IDEA Terminated with exit code 1,那必然是Maven的設(shè)置參數(shù)重置了,導(dǎo)致下載錯(cuò)誤引起的,本文給大家分享兩種解決方法,需要的朋友可以參考下
    2022-08-08
  • Spring?Boot與Spring?MVC?Spring對(duì)比及核心概念

    Spring?Boot與Spring?MVC?Spring對(duì)比及核心概念

    這篇文章主要為大家介紹了Spring?Boot與Spring?MVC?Spring的對(duì)比以及你需要了解的核心概念,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03

最新評(píng)論

莆田市| 城步| 建昌县| 福海县| 垦利县| 蓬安县| 淅川县| 光山县| 界首市| 七台河市| 罗源县| 嘉善县| 屯门区| 高淳县| 南皮县| 怀安县| 年辖:市辖区| 伽师县| 伊宁市| 九龙县| 大港区| 永年县| 聊城市| 杭锦旗| 兴业县| 石家庄市| 光山县| 乐东| 临江市| 于都县| 班玛县| 军事| 恭城| 海城市| 九江市| 靖安县| 云浮市| 南安市| 浮梁县| 苍梧县| 进贤县|