場(chǎng)景
阿里Java開發(fā)手冊(cè)嵩山版中明確指出:
1、BigDecimal的等值比較應(yīng)使用compareTo()方法,而不是equals()方法
equals()方法會(huì)比較值和精度(1.0與1.00返回結(jié)果為false),而compareTo()則會(huì)忽略精度
2、禁止使用構(gòu)造方法BigDecimal(double)的方式把double值轉(zhuǎn)換為BigDecimal對(duì)象
BigDecimal(double)存在精度損失風(fēng)險(xiǎn),在精確計(jì)算或值比較的場(chǎng)景中可能會(huì)導(dǎo)致業(yè)務(wù)邏輯異常
注:
博客:
霸道流氓氣質(zhì)的博客_CSDN博客-C#,架構(gòu)之路,SpringBoot領(lǐng)域博主
Java開發(fā)手冊(cè)為什么禁止使用BigDecimal的equals方法做等值比較?
BigDecimal,相信對(duì)于很多人來說都不陌生,很多人都知道他的用法,這是一種java.math 包中提供的一種可以用來
進(jìn)行精確運(yùn)算的類型。在進(jìn)行金額表示、金額計(jì)算等場(chǎng)景,不能使用 double、float 等類型,而是要使用對(duì)精度支持
更好的 BigDecimal。其內(nèi)部自帶了很多方法,如加,減,乘,除等運(yùn)算方法都是可以直接調(diào)用的。除了需要用
BigDecimal 表示數(shù)字和進(jìn)行數(shù)字運(yùn)算以外,代碼中還經(jīng)常需要對(duì)于數(shù)字進(jìn)行相等判斷。Java開發(fā)手冊(cè)中有說明:
BigDecimal的等值比較應(yīng)使用compareTo()方法,而不是equals()方法
equals()方法會(huì)比較值和精度(1.0與1.00返回結(jié)果為false),而compareTo()則會(huì)忽略精度。
看下面的示例:
??????? BigDecimal bigDecimal = new BigDecimal(1);
??????? BigDecimal bigDecimal1 = new BigDecimal(1);
??????? System.out.println(bigDecimal.equals(bigDecimal1));//true
??????? BigDecimal bigDecimal2 = new BigDecimal(1);
??????? BigDecimal bigDecimal3 = new BigDecimal(1.0);
??????? System.out.println(bigDecimal2.equals(bigDecimal3));//true
??????? BigDecimal bigDecimal4 = new BigDecimal("1");
??????? BigDecimal bigDecimal5 = new BigDecimal("1.0");
??????? System.out.println(bigDecimal4.equals(bigDecimal5));//false
通過以上代碼示例,我們發(fā)現(xiàn),在使用 BigDecimal 的 equals 方法對(duì) 1 和 1.0 進(jìn)行比較的時(shí)候,
有的時(shí)候是 true(當(dāng)使用 int、double 定義 BigDecimal 時(shí)),有的時(shí)候是false(當(dāng)使用 String 定義 BigDecimal 時(shí))。
查看源碼可知,equals會(huì)比較標(biāo)度scale,見源碼
BigDecimal 一共有以下 4 個(gè)構(gòu)造方法:
BigDecimal(int) 因?yàn)槭钦麛?shù),所以標(biāo)度就是 0
BigDecimal(double) 無論我們使用 new BigDecimal(0.1)還是 new BigDecimal(0.10)定義,他的近似值
都是0.1000000000000000055511151231257827021181583404541015625
這個(gè),那么他的標(biāo)度就是這個(gè)數(shù)字的位數(shù),即 55
BigDecimal(long) 因?yàn)槭钦麛?shù),所以標(biāo)度就是 0
BigDecimal(String)? BigDecimal(“1”)和 BigDecimal(“1.0”)的標(biāo)度不一樣
BigDecimal 中提供了 compareTo 方法,這個(gè)方法就可以只比較兩個(gè)數(shù)字的值,如果兩個(gè)數(shù)相等,則返回 0。
BigDecimal bigDecimal6 = new BigDecimal("1");
BigDecimal bigDecimal7 = new BigDecimal("1.0000");
System.out.println(bigDecimal6.compareTo(bigDecimal7)); //0
Java開發(fā)手冊(cè)為什么禁止使用double直接構(gòu)造BigDecimal
Java開發(fā)手冊(cè)中要求 禁止使用構(gòu)造方法BigDecimal(double)的方式把double值轉(zhuǎn)換為BigDecimal對(duì)象
說明:BigDecimal(double)存在精度損失風(fēng)險(xiǎn),在精確計(jì)算或值比較的場(chǎng)景中可能會(huì)導(dǎo)致業(yè)務(wù)邏輯異常
比如下面,實(shí)際存儲(chǔ)值為0.10000000149
BigDecimal bigDecimal = new BigDecimal(0.1F);
優(yōu)先推薦入?yún)镾tring 的構(gòu)造方法,或使用BigDecimal的valueOf方法,此方法其實(shí)內(nèi)部執(zhí)行了Double的toString,
而Double的toString按double的實(shí)際能表達(dá)的精度對(duì)尾數(shù)進(jìn)行了截?cái)唷?/p>
BigDecimal bigDecimal1 = new BigDecimal("0.1");
BigDecimal bigDecimal2 = BigDecimal.valueOf(0.1);
Java中doble為什么不精確?
十進(jìn)制小數(shù)轉(zhuǎn)成二進(jìn)制,一般采用”乘 2 取整,順序排列”方法,如 0.625 轉(zhuǎn)成二進(jìn)制的表示為 0.101。
但是,并不是所有小數(shù)都能轉(zhuǎn)成二進(jìn)制,如 0.1 就不能直接用二進(jìn)制表示,他的二進(jìn)制是 0.000110011001100...
這是一個(gè)無限循環(huán)小數(shù)。所以,計(jì)算機(jī)是沒辦法用二進(jìn)制精確的表示 0.1 的。也就是說,在計(jì)算機(jī)中,
很多小數(shù)沒辦法精確的使用二進(jìn)制表示出來。在 Java 中,使用 float 和 double 分別用來表示單精度浮點(diǎn)數(shù)和雙精度浮點(diǎn)數(shù)。文章來源:http://www.zghlxwxcb.cn/news/detail-467411.html
所謂精度不同,可以簡(jiǎn)單的理解為保留有效位數(shù)不同。采用保留有效位數(shù)的方式近似的表示小數(shù)。文章來源地址http://www.zghlxwxcb.cn/news/detail-467411.html
到了這里,關(guān)于Java開發(fā)手冊(cè)中為什么禁止使用BigDecimal的equals方法做等值比較已經(jīng)為什么禁止使用double直接構(gòu)造BigDecimal的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!