为什么下面的代码会引发如下所示的异常?
BigDecimal a = new BigDecimal("1.6");
BigDecimal b = new BigDecimal("9.2");
a.divide(b) // results in the following exception.
例外:
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
来自Java 11 BigDecimal文档:
When a MathContext object is supplied with a precision setting of 0 (for example, MathContext.UNLIMITED), arithmetic operations are exact, as are the arithmetic methods which take no MathContext object. (This is the only behavior that was supported in releases prior to 5.)
As a corollary of computing the exact result, the rounding mode setting of a MathContext object with a precision setting of 0 is not used and thus irrelevant. In the case of divide, the exact quotient could have an infinitely long decimal expansion; for example, 1 divided by 3.
If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown. Otherwise, the exact result of the division is returned, as done for other operations.
要修复,你需要做这样的事情:
a.divide(b, 2, RoundingMode.HALF_UP)
其中2是比例和round mode。HALF_UP是舍入模式
欲了解更多细节,请参阅这篇博客文章。
BigDecimal的答案抛出算术异常
public static void main(String[] args) {
int age = 30;
BigDecimal retireMentFund = new BigDecimal("10000.00");
retireMentFund.setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal yearsInRetirement = new BigDecimal("20.00");
String name = " Dennis";
for ( int i = age; i <=65; i++){
recalculate(retireMentFund,new BigDecimal("0.10"));
}
BigDecimal monthlyPension = retireMentFund.divide(
yearsInRetirement.divide(new BigDecimal("12"), new MathContext(2, RoundingMode.CEILING)), new MathContext(2, RoundingMode.CEILING));
System.out.println(name+ " will have £" + monthlyPension +" per month for retirement");
}
public static void recalculate (BigDecimal fundAmount, BigDecimal rate){
fundAmount.multiply(rate.add(new BigDecimal("1.00")));
}
在divide方法调用中添加MathContext对象,并调整精度和舍入模式。这应该可以解决您的问题
我也有同样的问题,因为我的代码行是:
txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");
我改为这个,阅读之前的答案,因为我没有写十进制精度:
txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");
4是十进制精度
AND RoundingMode是Enum常量,你可以选择其中任何一个
上,下,天花板,地板,一半向下,一半均匀,一半向上
在本例中,HALF_UP的结果如下:
2.4 = 2
2.5 = 3
2.7 = 3
你可以在这里查看RoundingMode信息:http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/