web-dev-qa-db-ja.com

ArithmeticException: "終了しない10進数展開。表現可能な正確な10進数結果がない"

次のコードがなぜ以下に示す例外を発生させるのですか?

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.
449
Jason

Java 8 docsから:

MathContextオブジェクトの精度設定が0(MathContext.UNLIMITEDなど)の場合、算術演算はMathContextオブジェクトを取らない算術メソッドと同様に正確です。 (これが5より前のリリースでサポートされていた唯一の動作です。)

正確な結果を計算することの必然的結果として、精度設定が0のMathContextオブジェクトの丸めモード設定は使用されず、したがって無関係です。除算の場合、正確な商は無限に長い10進展開を持つことができます。たとえば、1を3で割った値です。

商に非終端10進展開があり、演算が正確な結果を返すように指定されている場合は、ArithmeticExceptionがスローされます。それ以外の場合は、他の操作の場合と同様に、除算の正確な結果が返されます。

修正するには、このようにする必要があります

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/

762
DVK

精度と丸めモードを指定していないからです。 BigDecimalは、10、20、5000、または無限小数位を使用する可能性があると訴えていますが、それでも数値を正確に表すことはできません。それで、あなたに間違ったBigDecimalを与える代わりに、それはただあなたに鞭打ちます。

しかし、もしあなたがRoundingModeと精度を供給すれば、それは(例えば1.333333333から無限大へ1.3333のようなものに)変換することができるでしょう。しかしあなたはプログラマーとしてあなたが望む精度をそれに伝える必要があります。 '。

72
David Bullock

できるよ

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

47
MindBrain

このような問題を修正するために、私は以下のコードを使用しました

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

2は精度です。これで問題は解決しました。

13
Prahlad

私のコード行は次のとおりです。

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

私は10進数の精度を書いていなかったので、前の答えを読んで、これに変更します。

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

4は10進数の精度です

AND RoundingModeはEnum定数です。この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

それは結果を丸めることの問題です、私のための解決策は以下の通りです。

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

に対する回答 - BigDecimalが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オブジェクトを追加して、精度と丸めモードを調整します。これで問題は解決するはずです

1
Poorna Chander

これは、Bigdecimalが失われていないためです。たとえば、1/3を除算すると、10進数から無限大までが繰り返されます。 0.33333333 ...理論的には、元に戻すと正確な結果が得られます。しかし、無限大の数はフローオーバースタックを生成し、この場合は例外が発生します。

解決策:

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

または

n1.divide(n2,RoundingMode.HALF_UP);

この場合、あなたの結果は四捨五入によって切り捨てられません

0
Leo Lima

あなたのプログラムは10進数のためにどの精度を使うべきか知らないのでそれは投げる:

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
0
Miloš Ojdanić