Java BigDecimal使用及基本運(yùn)算(推薦)
BigDecimal簡(jiǎn)介
Java在java.math包中提供的API類BigDecimal,用來(lái)對(duì)超過(guò)16位有效位的數(shù)進(jìn)行精確的運(yùn)算。雙精度浮點(diǎn)型變量double可以處理16位有效數(shù)。在實(shí)際應(yīng)用中,需要對(duì)更大或者更小的數(shù)進(jìn)行運(yùn)算和處理。float和double只能用來(lái)做科學(xué)計(jì)算或者是工程計(jì)算,在商業(yè)計(jì)算中要用java.math.BigDecimal。BigDecimal所創(chuàng)建的是對(duì)象,我們不能使用傳統(tǒng)的+、-、*、/等算術(shù)運(yùn)算符直接對(duì)其對(duì)象進(jìn)行數(shù)學(xué)運(yùn)算,而必須調(diào)用其相對(duì)應(yīng)的方法。方法中的參數(shù)也必須是BigDecimal的對(duì)象。構(gòu)造器是類的特殊方法,專門(mén)用來(lái)創(chuàng)建對(duì)象,特別是帶有參數(shù)的對(duì)象。
提起B(yǎng)igDecimal,相信大家都使用過(guò),之所以總結(jié)這篇呢,是因?yàn)樽罱l(fā)現(xiàn)項(xiàng)目中使用的不是太規(guī)范,在某些場(chǎng)景下甚至出現(xiàn)代碼拋出異常的情況,
所以就總結(jié)了這篇,希望大家在使用時(shí),可以少踩一些坑。
1. 基本運(yùn)算
1.1 加法
BigDecimal number1 = new BigDecimal('88.88');BigDecimal number2 = new BigDecimal('11.12');BigDecimal number3 = number1.add(number2);System.out.println('number1 add number2 = ' + number3);
輸出結(jié)果:
number1 add number2 = 100.00
1.2 減法
BigDecimal number1 = new BigDecimal('88.88');BigDecimal number2 = new BigDecimal('11.12');BigDecimal number3 = number1.subtract(number2);System.out.println('number1 subtract number2 = ' + number3);
輸出結(jié)果:
number1 subtract number2 = 77.76
1.3 乘法
BigDecimal number1 = new BigDecimal('88.88');BigDecimal number2 = new BigDecimal('11.12');BigDecimal number3 = number1.multiply(number2);System.out.println('number1 multiply number2 = ' + number3);
輸出結(jié)果:
number1 multiply number2 = 988.3456
1.4 除法
BigDecimal number1 = new BigDecimal('88');BigDecimal number2 = new BigDecimal('11');BigDecimal number3 = number1.divide(number2);System.out.println('number1 divide number2 = ' + number3);
輸出結(jié)果:
number1 divide number2 = 8
因?yàn)樯厦?個(gè)數(shù)可以整除,所以這么用沒(méi)有問(wèn)題,不過(guò)一但不能被整除,這么用就會(huì)有潛在的風(fēng)險(xiǎn),會(huì)拋出java.lang.ArithmeticException異常,所以強(qiáng)烈建議像下面這樣使用:
BigDecimal number1 = new BigDecimal('88.88');BigDecimal number2 = new BigDecimal('11.12');BigDecimal number3 = number1.divide(number2, 2, RoundingMode.HALF_UP);System.out.println('number1 divide number2 = ' + number3);
輸出結(jié)果:
number1 divide number2 = 7.99
此時(shí)使用的divide()方法源碼如下所示:
public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) { return divide(divisor, scale, roundingMode.oldMode);}
這里的scale指的是要保留的小數(shù)位數(shù),我們傳的是2,即保留2位小數(shù)。
這里的roundingMode指的是舍入模式,我們這里傳的是RoundingMode.HALF_UP,即經(jīng)常使用的四舍五入模式。
1.5 保留小數(shù)位數(shù)
如果我們想對(duì)BigDecimal類型保留小數(shù)位數(shù),可以使用setScale()方法,使用方法如下所示:
BigDecimal number1 = new BigDecimal('88.88');BigDecimal number2 = new BigDecimal('11.12');BigDecimal number3 = number1.multiply(number2);System.out.println('number1 multiply number2 = ' + number3);// 保留3位小數(shù),四舍五入BigDecimal number4 = number3.setScale(3, RoundingMode.HALF_UP);System.out.println('number3 setScale = ' + number4);
輸出結(jié)果:
number1 multiply number2 = 988.3456
number3 setScale = 988.346
1.6 比較大小
BigDecimal比較大小,可以使用compareTo()方法,使用方法如下所示:
BigDecimal number1 = new BigDecimal('88.88');BigDecimal number2 = new BigDecimal('11.11');BigDecimal number3 = new BigDecimal('99.99');BigDecimal number4 = new BigDecimal('88.88');System.out.println('number1 compareTo number2 = ' + number1.compareTo(number2));System.out.println('number1 compareTo number3 = ' + number1.compareTo(number3));System.out.println('number1 compareTo number4 = ' + number1.compareTo(number4));
輸出結(jié)果:
number1 compareTo number2 = 1
number1 compareTo number3 = -1
number1 compareTo number4 = 0
由輸出結(jié)果可以看出:
當(dāng)number1小于number2時(shí),返回-1,
當(dāng)number1等于number2時(shí),返回0,
當(dāng)number1大于number2時(shí),返回1。
2. 踩坑總結(jié)
2.1 NullPointerException異常
在使用BigDecimal類型進(jìn)行計(jì)算時(shí),比如上面提到的加、減、乘、除、比較大小時(shí),一定要保證參與計(jì)算的兩個(gè)值不能為空,否則會(huì)拋出java.lang.NullPointerException異常。
比如下面的2段代碼,都會(huì)拋出異常:
BigDecimal number1 = null;BigDecimal number2 = new BigDecimal('11.12');BigDecimal number3 = number1.add(number2);System.out.println('number1 add number2 = ' + number3);
BigDecimal number1 = new BigDecimal('88.88');BigDecimal number2 = null;BigDecimal number3 = number1.add(number2);System.out.println('number1 add number2 = ' + number3);
拋出的異常如下圖所示:
2.2 ArithmeticException異常
一次在使用BigDecimal的divide方法時(shí),拋出java.lang.ArithmeticException異常,錯(cuò)誤代碼如下所示:
// 含稅金額BigDecimal inclusiveTaxAmount = new BigDecimal('1000');// 稅率BigDecimal taxRate = new BigDecimal('0.13');// 不含稅金額 = 含稅金額 / (1+稅率)BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate));System.out.println(exclusiveTaxAmount);
運(yùn)行時(shí)拋出以下異常:
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
報(bào)錯(cuò)原因是因?yàn)闊o(wú)法整除,導(dǎo)致結(jié)果是無(wú)限循環(huán)小數(shù):
解決方案是指定下舍入模式,比如我們最常用的四舍五入模式:
// 不含稅金額 = 含稅金額 / (1+稅率)BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate),RoundingMode.HALF_UP);
此時(shí)不再報(bào)錯(cuò),輸出結(jié)果為:
885
但這里我的需求是保留2位小數(shù),四舍五入,因此代碼應(yīng)該是下面這樣的:
// 不含稅金額 = 含稅金額 / (1+稅率)BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate), 2, RoundingMode.HALF_UP);
此時(shí)的輸出結(jié)果為:
884.96
如果你的IDEA裝了阿里巴巴代碼規(guī)范插件,如果不指定RoundingMode,會(huì)有下面這樣的提示:
3. 使用規(guī)范
盡量不要在項(xiàng)目中使用new BigDecimal('0'),而是使用BigDecimal提供的常量BigDecimal.ZERO。
BigDecimal zero = BigDecimal.ZERO;BigDecimal one = BigDecimal.ONE;BigDecimal ten = BigDecimal.TEN;
總結(jié)
到此這篇關(guān)于Java BigDecimal使用指南針(推薦)的文章就介紹到這了,更多相關(guān)Java BigDecimal使用內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. 使用 kind 和 Docker 啟動(dòng)本地的 Kubernetes環(huán)境2. ASP基礎(chǔ)入門(mén)第八篇(ASP內(nèi)建對(duì)象Application和Session)3. XML入門(mén)精解之結(jié)構(gòu)與語(yǔ)法4. Idea如何去除Mapper警告方法解析5. idea設(shè)置自動(dòng)導(dǎo)入依賴的方法步驟6. IntelliJ IDEA設(shè)置編碼格式的方法7. idea設(shè)置代碼格式化的方法步驟8. idea自定義快捷鍵的方法步驟9. IntelliJ IDEA設(shè)置默認(rèn)瀏覽器的方法10. idea重置默認(rèn)配置的方法步驟
