web-dev-qa-db-ja.com

BigDecimal.divideからの「終了しない10進展開」例外の原因は何ですか?

私は以前BigDecimalsを使用しましたが、あまり頻繁ではなく、今朝何かに取り組んでいて、次の例外が発生し続けました。

Exception in thread "main" Java.lang.ArithmeticException: Non-terminating decimal expansion;
no exact representable decimal result.
    at Java.math.BigDecimal.divide(BigDecimal.Java:1594)

私はスケールを設定し、丸めを使用して問題を排除しようとしました:

    BigDecimal bd1 = new BigDecimal(1131).setScale(2,BigDecimal.ROUND_HALF_UP);
    BigDecimal bd2 = new BigDecimal(365).setScale(2,BigDecimal.ROUND_HALF_UP);
    BigDecimal bd3 = bd1.divide(bd2).setScale(2,BigDecimal.ROUND_HALF_UP);
    System.out.println("result: " + bd3);

ただし、同じ例外が引き続き発生します。間違いを犯した場所を教えてくれる人はいますか?

22
ChadNC

divideを使用する場合、正確な結果に無限の小数が含まれる場合(これはあなたの場合です)に、MathContextを使用する必要があります。

MathContext mc = new MathContext(2, RoundingMode.HALF_UP);
BigDecimal bd3 = bd1.divide(bd2, mc);

または、代わりに:

BigDecimal bd3 = bd1.divide(bd2, RoundingMode.HALF_UP);
53
assylias

ここに問題があります

_bd1.divide(bd2)
_

オーバーロードされたdivide()メソッドの1つを使用して、丸めモード(さまざまな形式)を使用する必要があります-終了しない分数では中間結果を既に丸める必要があるため、除算後に丸めることはできません、または無限のストレージスペースが必要です。

4

デフォルトでは、BigDecimalは指定された除算式の正確な値を返そうとします。このため、無限小数展開のために正確な値を決定できない場合、ArithmeticExceptionがスローされます。これの基本的な例は、1を3で除算し、結果として3分の1になることです。この値は、10進表記で正確に表すことはできません。

2
FThompson

この問題は、10進数が繰り返される操作(除算)が原因で発生します。

解決策は、除算の実行時にscaleを指定することです。次に例を示します。

BigDecimal one = new BigDecimal("1");
BigDecimal three = new BigDecimal("3");
BigDecimal oneDivThree = one.divide(three, 200, RoundingMode.HALF_UP);
1
Neil Coffey

分割のためにこのエラーが発生しています:

  1. デフォルトでは、BigDecimalは常に操作の正確な結果を返そうとします。
  2. このため、1を3で除算するような特定の除算演算では、正確な商は無限に長い10進展開になります。これにより、上記のように除算操作が失敗し、エラーがスローされます。

これを防ぐために、除算方法内にスケールと丸めモード(BigDecimalsの作成時に行ったように)を提供します。

here から取得。作業部門のコード例も提供されています。

BigDecimalのJavaドキュメント も参照してください。

1
keyser

修正するには、次のように3番目のステーメントを変更する必要があります。

BigDecimal bd1 = new BigDecimal(1131).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal bd2 = new BigDecimal(365).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal bd3 = bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP);
System.out.println("result: " + bd3);
0
The Tran