为什么下面的代码会引发如下所示的异常?

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.lang.ArithmeticException: Non-terminating decimal expansion

绕过异常的解决方案:

MathContext precision = new MathContext(int setPrecisionYouWant); // example 2
BigDecimal a = new BigDecimal("1.6",precision);
BigDecimal b = new BigDecimal("9.2",precision);
a.divide(b) // result = 0.17

其他回答

因为你没有指定精度和舍入模式。BigDecimal抱怨说,它可以使用10位、20位、5000位或无穷大的小数位,但它仍然不能给您一个精确的数字表示。所以它不会给你一个不正确的BigDecimal,而是会向你抱怨。

然而,如果你提供了一个RoundingMode和一个精度,那么它将能够转换(例如。从1.333333333到无穷到1.3333……但作为程序员,你需要告诉它你“满意”的精度是多少。

这是一个舍入结果的问题,对我来说解决方案如下。

divider.divide(dividend,RoundingMode.HALF_UP);

来自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/