次のコードがなぜ以下に示す例外を発生させるのですか?
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 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/
精度と丸めモードを指定していないからです。 BigDecimalは、10、20、5000、または無限小数位を使用する可能性があると訴えていますが、それでも数値を正確に表すことはできません。それで、あなたに間違ったBigDecimalを与える代わりに、それはただあなたに鞭打ちます。
しかし、もしあなたがRoundingModeと精度を供給すれば、それは(例えば1.333333333から無限大へ1.3333のようなものに)変換することができるでしょう。しかしあなたはプログラマーとしてあなたが望む精度をそれに伝える必要があります。 '。
できるよ
a.divide(b, MathContext.DECIMAL128)
必要なビット数は32、64、128のいずれかを選択できます。
このリンクをチェックしてください。
このような問題を修正するために、私は以下のコードを使用しました
a.divide(b, 2, RoundingMode.HALF_EVEN)
2は精度です。これで問題は解決しました。
私のコード行は次のとおりです。
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/
それは結果を丸めることの問題です、私のための解決策は以下の通りです。
divider.divide(dividend,RoundingMode.HALF_UP);
に対する回答 - 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オブジェクトを追加して、精度と丸めモードを調整します。これで問題は解決するはずです
これは、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);
この場合、あなたの結果は四捨五入によって切り捨てられません
あなたのプログラムは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