首页 文章

ArithmeticException:“非终止十进制扩展;没有确切的可表示的小数结果“

提问于
浏览
434

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

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.

9 回答

  • 1

    来自Java 8文档:

    当MathContext对象的精度设置为0时(例如,MathContext.UNLIMITED),算术运算是精确的,算术方法也不是MathContext对象 . (这是5之前版本中唯一支持的行为 . )作为计算精确结果的必然结果,不使用精度设置为0的MathContext对象的舍入模式设置,因此无关紧要 . 在除法的情况下,精确商可以具有无限长的十进制扩展;例如,1除以3.如果商具有非终止十进制扩展并且指定了操作以返回精确结果,则抛出ArithmeticException . 否则,返回除法的确切结果,与其他操作一样 .

    To fix, you need to do something like this

    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-terminating-decimal-expansion-error/

  • 13

    因为您没有指定精度和舍入模式 . BigDecimal抱怨它可以使用10,20,000,或无限小数位,但它仍然无法准确表示数字 . 因此,它不会给你一个不正确的BigDecimal,它只会对你产生影响 .

    但是,如果你提供一个RoundingMode和一个精度,那么它将能够转换(例如1.333333333到无穷大到类似于1.3333 ...但是你作为程序员需要告诉它你对'满意'的准确度” .

  • 729

    你可以做

    a.divide(b, MathContext.DECIMAL128)
    

    您可以选择所需的位数32,64,128 .

    看看这个链接:

    http://edelstein.pebbles.cs.cmu.edu/jadeite/main.php?api=java6&state=class&package=java.math&class=MathContext

  • 45

    为了解决这个问题我在下面的代码中使用过

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

    2是精度 . 现在问题解决了 .

  • 0

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

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

    我改为这个,阅读之前的答案,因为我没有写小数精度:

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

    4是Decimal Precion

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

    在这个案例HALF_UP中,将得到以下结果:

    2.4 = 2   
    2.5 = 3   
    2.7 = 3
    

    你可以在这里查看 RoundingMode 信息:http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

  • 6

    回答BigDecimal throws ArithmeticException

    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对象并调整精度和舍入模式 . 这应该可以解决您的问题

  • 71

    这是一个舍入结果的问题,我的解决方案如下 .

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

    这是因为Bigdecimal没有丢失,例如,如果你除以1/3,它将导致重复的十进制到无穷大 . 0.33333333 ...理论上如果你再乘以,你会得到确切的结果 . 但是,无穷大数字将生成堆栈溢出流,在这种情况下启动异常 .

    我的解决方案

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

    在这种情况下,Rounding不会削减您的结果

  • 0

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

    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
    

相关问题