关于java:ArithmeticException:“非终止十进制扩展;

ArithmeticException: “Non-terminating decimal expansion; no exact representable decimal result”

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

1
2
3
BigDecimal a = new BigDecimal("1.6");
BigDecimal b = new BigDecimal("9.2");
a.divide(b) // results in the following exception.

——

1
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.


从Java 8文档:

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.

要修复,您需要执行以下操作:

1
2
3
a.divide(b, 2, RoundingMode.HALF_UP)

where 2 is precision and RoundingMode.HALF_UP is rounding mode

更多详细信息:http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-termining-decimal-expansion-error/


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

然而,如果你提供了一个圆形模式和一个精度,那么它将能够转换(如1.33333333 33到无穷大,如1.3333…但是作为程序员,你需要告诉它你"满意"的精度。


你可以的

1
a.divide(b, MathContext.DECIMAL128)

您可以选择所需的位数32,64128。

查看此链接:

http://edelstein.pebbles.cs.cmu.edu/jadeite/main.php?API = java6&;


为了解决这个问题,我用了下面的代码

1
a.divide(b, 2, RoundingMode.HALF_EVEN)

2是精确的。现在问题解决了。


我也有同样的问题,因为我的代码行是:

1
txtTotalInvoice.setText(var1.divide(var2).doubleValue() +"");

我改为读前面的答案,因为我没有写小数精度:

1
txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() +"");

4是小数精度

RoundingMode是枚举常量,您可以选择其中任何一个UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP

在这种情况下,一半以上,将产生以下结果:

1
2
3
2.4 = 2  
2.5 = 3  
2.7 = 3

您可以在以下位置查看RoundingMode信息:http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/


这是一个取整结果的问题,我的解决方法如下。

1
divider.divide(dividend,RoundingMode.HALF_UP);


BigDecimal引发算术异常的答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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对象,并调整精度和舍入模式。这样可以解决你的问题


您的程序不知道十进制数字的精度,因此它抛出:

1
java.lang.ArithmeticException: Non-terminating decimal expansion

绕过异常的解决方案:

1
2
3
4
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没有丢失,例如,如果将1/3除,它将导致重复的十进制到无穷大。0.33333333…理论上,如果你再乘以,你会得到确切的结果。但是,一个无穷大的数字将在流上生成堆栈,在这种情况下,将启动异常。

解决方案:

1
2
3
4
5
6
 try {
     result = n1.divide(n2);
 } catch (ArithmeticException e){
     Log.d("Error bigdecimal", e.toString());
     result = (n1.doubleValue() / n2.doubleValue());
 };

1
n1.divide(n2,RoundingMode.HALF_UP);

在这种情况下,您的结果不会被四舍五入削减。