今天工作的时候碰到了前端录入整数时可以正常运行,但是录入小数时会出现异常。一顿寻找后发现是在Action方法中将BigDecimal的精度定义为了0,所以才会出现精度异常。解决办法是将精度设置为2并且后边多出的位数直接舍弃。
异常为:
java.lang.ArithmeticException:Rounding necessary
导致异常的代码:
prpLcheckDuty.setIndemnityDutyRate(prpLcheckDuty.getIndemnityDutyRate().setScale(0));
修改后的代码:
prpLcheckDuty.setIndemnityDutyRate(prpLcheckDuty.getIndemnityDutyRate().setScale(2,BigDecimal.ROUND_DOWN))
总结了一下在使用BigDecimal数据类型进行计算时可能会出现java.lang.ArithmeticException的问题:
- 当除数为0时,这种情况比较常见,所以我们在进行除法运算之前先判断下除数是否为0。
- 如果运算的结果是无限循环的小数,并且在除的时候没有对结果设置精确的位数,这时就会抛出异常,这种情况比较容易被忽视,抛出异常后一般都会考虑是否为0,因此,要特别注意。
- 当我们设置了结果的舍入模式是:ROUND_UNNECESSARY模式时,如果确保了计算的结果是精确的,则不会抛出异常,否则,就会抛出ArithmeticException异常。
- 设置的精度小于录入的位数时可能会出现java.long.ArithmeticException,如果设置的精度大于录入的位数时,数字的末尾会自动用0来补位。
设置的精度小于录入位数实例代码:
public class Test {
public static void main(String[] args) {
BigDecimal bigDecimal1 = new BigDecimal(98.01111);
System.out.println(bigDecimal1.setScale(2));
BigDecimal bigDecimal2 = new BigDecimal("98.01111");
System.out.println(bigDecimal2.setScale(2));
}
}
设置的精度大于录入位数实例代码:
public class Test {
public static void main(String[] args) {
BigDecimal bigDecimal = new BigDecimal("98.01111");
System.out.println(bigDecimal.setScale(10,BigDecimal.ROUND_DOWN));
}
}
在进行金额等比较敏感的数据运算时,我们可以用BigDecimal类型进行运算:java.math.BigDecimal,此类为我们提供了四种构造方法,我们常用的两种是:BigDecimal(double) 和 BigDecimal(String)
System.out.println(new BigDecimal(1.01));
System.out.println(new BigDecimal("1.01"));
使用BigDecimal类型,传入double型值的时候,精确度乱掉问题:
此构造方法的结果有一定的不可预知性。有人可能认为在 Java 中写入 new BigDecimal(0.1) 所创建的BigDecimal 正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为 0.1 无法准确地表示为 double (或者说对于该情况,不能表示为任何有限长度的二进制小数),这样,传入 到构造方法的值不会正好等于0.1(虽然表面上等于该值)
另一方面,String 构造方法是完全可预知的:写入 new BigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用 String 构造方法。
当 double 必须用作 BigDecimal 的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用Double.toString(double) 方法,然后使用 BigDecimal(String) 构造方法,将 double 转换为String。要获取该结果,请使用 static valueOf(double) 方法。
解决方案:
传入double类型值时,调用下toString方法。
BigDecimal详解:
作用:可以用来精确计算
构造方法:可以传入double 和String ,推荐使用<青色>String 类型</青色>
常用方法:
add(BigDecimal对象):加
subtract (BigDecimal对象):减
multiply (BigDecimal对象):乘
divide (BigDecimal对象):除
divide (BigDecimal对象,精确几位,舍入模式):除
参数1:表示参与运算的BigDecimal 对象。
参数2:表示小数点后面精确到多少位
参数3:舍入模式
BigDecimal.ROUND_UP 进一法
BigDecimal.ROUND_FLOOR 去尾法
BigDecimal.ROUND_HALF_UP 四舍五入
注意事项:
BigDecimal是用来进行精确计算的
创建BigDecimal的对象,构造方法使用参数类型为字符串的。
四则运算中的除法,如果除不尽请使用divide的三个参数的方法。