Java BigDecimal使用及基本運(yùn)算(推薦)
BigDecimal簡(jiǎn)介
Java在java.math包中提供的API類BigDecimal,用來對(duì)超過16位有效位的數(shù)進(jìn)行精確的運(yùn)算。雙精度浮點(diǎn)型變量double可以處理16位有效數(shù)。在實(shí)際應(yīng)用中,需要對(duì)更大或者更小的數(shù)進(jìn)行運(yùn)算和處理。float和double只能用來做科學(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)造器是類的特殊方法,專門用來創(chuàng)建對(duì)象,特別是帶有參數(shù)的對(duì)象。
提起B(yǎng)igDecimal,相信大家都使用過,之所以總結(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ù)可以整除,所以這么用沒有問題,不過一但不能被整除,這么用就會(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法整除,導(dǎo)致結(jié)果是無限循環(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)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解java中BigDecimal精度問題
- java 使用BigDecimal進(jìn)行貨幣金額計(jì)算的操作
- java中BigDecimal和0比較的示例代碼
- Java之BigDecimal實(shí)現(xiàn)詳解
- Java double轉(zhuǎn)BigDecimal的注意事項(xiàng)說明
- Java用BigDecimal類解決Double類型精度丟失的問題
- Java踩坑記錄之BigDecimal類
- Java使用BigDecimal精確運(yùn)算浮點(diǎn)數(shù)
- 如何使用BigDecimal實(shí)現(xiàn)Java開發(fā)商業(yè)計(jì)算
- 詳解Java中的BigDecimal
- Java中BigDecimal類的使用詳解
- Java Bigdecimal使用原理詳解
- Java中BigDecimal類與int、Integer使用總結(jié)
- Java BigInteger類,BigDecimal類,Date類,DateFormat類及Calendar類用法示例
- 淺談Java基礎(chǔ)知識(shí)之BigDecimal
相關(guān)文章
AsyncHttpClient exception異常源碼流程解析
這篇文章主要為大家介紹了AsyncHttpClient的exception源碼流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12MacBook Java開發(fā)環(huán)境搭建的詳細(xì)步驟(新手必備)
本文主要介紹了MacBook Java開發(fā)環(huán)境搭建,文中通過圖文示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07springboot打war包部署到外置tomcat容器的方法
這篇文章主要介紹了springboot]打war包部署到外置tomcat容器,在這需要注意的是在boot-launch.war在tomcat?webapps目錄里面解壓到boot-launch文件夾,感興趣的朋友跟隨小編一起看看吧2022-04-04SpringBoot實(shí)現(xiàn)Server-Sent Events(SSE)的使用完整指南
使用SpringBoot實(shí)現(xiàn)Server-Sent Events(SSE)可以有效處理實(shí)時(shí)數(shù)據(jù)推送需求,具有單向通信、輕量級(jí)和高實(shí)時(shí)性等優(yōu)勢(shì),本文詳細(xì)介紹了在SpringBoot中創(chuàng)建SSE端點(diǎn)的步驟,并通過代碼示例展示了客戶端如何接收數(shù)據(jù),適用于實(shí)時(shí)通知、數(shù)據(jù)展示和在線聊天等場(chǎng)景2024-09-09java并發(fā)編程之進(jìn)程和線程調(diào)度基礎(chǔ)詳解
這篇文章主要介紹了java并發(fā)編程之進(jìn)程和線程調(diào)度基礎(chǔ),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06SpringBoot?整合ChatGPT?API項(xiàng)目實(shí)戰(zhàn)教程
這篇文章主要介紹了SpringBoot整合ChatGPT API項(xiàng)目實(shí)戰(zhàn)教程,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05Java算法練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(2)
方法下面小編就為大家?guī)硪黄狫ava算法的一道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07