问题
先看一个例子:
public static void main(String[] args){
BigDecimal num1 = new BigDecimal(3);
BigDecimal num2 = new BigDecimal(7);
BigDecimal num3 = num1.divide(num2).setScale(2);
System.out.println(num3);
}
这段代码运行过程中会抛出一个异常
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result
意思大概是运算异常,没有可精确表示的十进制结果。
原因
因为结果除不尽,所以在 divide 的时候已经抛出了该异常,并不会进行保留两位小数的运算。
解决方案
在使用BigDecimal进行除法运算时,最好使用divide的重载方法
/**
* divisor 除数
* scale 保留几位小数
* roundingMode 舍入模式
*/
public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {
return divide(divisor, scale, roundingMode.oldMode);
}
所以写成以下方式就没问题了
public static void main(String[] args){
BigDecimal num1 = new BigDecimal(3);
BigDecimal num2 = new BigDecimal(7);
BigDecimal num3 = num1.divide(num2,2,BigDecimal.ROUND_HALF_DOWN);
System.out.println(num3);
}
备注:关于RoundingMode的几种模式
- ROUND_UP
向远离零的方向舍入。向外取整模式 - ROUND_DOWN
向接近零的方向舍入。向内取整模式 - ROUND_CEILING
向正无穷大的方向舍入。向上取整模式 - ROUND_FLOOR
向负无穷大的方向舍入。向下取整模式 - ROUND_HALF_UP
向“最接近的”整数舍入。四舍五入模式 - ROUND_HALF_DOWN
向“最接近的”整数舍入。五舍六入模式 - ROUND_HALF_EVEN
若(舍入位大于5)或者(舍入位等于5且前一位为奇数),则对舍入部分的前一位数字加1;若(舍入位小于5)或者(舍入位等于5且前一位为偶数),则直接舍弃。即为银行家舍入模式。 - ROUND_UNNECESSARY
具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。