提起BigDecimal,相信大家都使用過,之所以總結這篇呢,是因為最近發現專案中使用的不是太規范,在某些場景下甚至出現代碼拋出例外的情況,
所以就總結了這篇,希望大家在使用時,可以少踩一些坑,
1. 基本運算
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);
輸出結果:
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);
輸出結果:
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);
輸出結果:
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);
輸出結果:
number1 divide number2 = 8
因為上面2個數可以整除,所以這么用沒有問題,不過一但不能被整除,這么用就會有潛在的風險,會拋出java.lang.ArithmeticException例外,所以強烈建議像下面這樣使用:
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);
輸出結果:
number1 divide number2 = 7.99
此時使用的divide()方法原始碼如下所示:
public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {
return divide(divisor, scale, roundingMode.oldMode);
}
這里的scale指的是要保留的小數位數,我們傳的是2,即保留2位小數,
這里的roundingMode指的是舍入模式,我們這里傳的是RoundingMode.HALF_UP,即經常使用的四舍五入模式,
1.5 保留小數位數
如果我們想對BigDecimal型別保留小數位數,可以使用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位小數,四舍五入
BigDecimal number4 = number3.setScale(3, RoundingMode.HALF_UP);
System.out.println("number3 setScale = " + number4);
輸出結果:
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));
輸出結果:
number1 compareTo number2 = 1
number1 compareTo number3 = -1
number1 compareTo number4 = 0
由輸出結果可以看出:
當number1小于number2時,回傳-1,
當number1等于number2時,回傳0,
當number1大于number2時,回傳1,
2. 踩坑總結
2.1 NullPointerException例外
在使用BigDecimal型別進行計算時,比如上面提到的加、減、乘、除、比較大小時,一定要保證參與計算的兩個值不能為空,否則會拋出java.lang.NullPointerException例外,
比如下面的2段代碼,都會拋出例外:
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方法時,拋出java.lang.ArithmeticException例外,錯誤代碼如下所示:
// 含稅金額
BigDecimal inclusiveTaxAmount = new BigDecimal("1000");
// 稅率
BigDecimal taxRate = new BigDecimal("0.13");
// 不含稅金額 = 含稅金額 / (1+稅率)
BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate));
System.out.println(exclusiveTaxAmount);
運行時拋出以下例外:
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

報錯原因是因為無法整除,導致結果是無限回圈小數:

解決方案是指定下舍入模式,比如我們最常用的四舍五入模式:
// 不含稅金額 = 含稅金額 / (1+稅率)
BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate),RoundingMode.HALF_UP);
此時不再報錯,輸出結果為:
885
但這里我的需求是保留2位小數,四舍五入,因此代碼應該是下面這樣的:
// 不含稅金額 = 含稅金額 / (1+稅率)
BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate), 2, RoundingMode.HALF_UP);
此時的輸出結果為:
884.96
如果你的IDEA裝了阿里巴巴代碼規范插件,如果不指定RoundingMode,會有下面這樣的提示:

3. 使用規范
盡量不要在專案中使用new BigDecimal("0"),而是使用BigDecimal提供的常量BigDecimal.ZERO,
BigDecimal zero = BigDecimal.ZERO;
BigDecimal one = BigDecimal.ONE;
BigDecimal ten = BigDecimal.TEN;
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/43135.html
標籤:Java
