30

以前に 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);

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

4

6 に答える 6

65

有限小数は丸めが必要です

使用するときは、正確な結果の小数点以下の桁数が無限である場合に備えて、 withdivideを使用する必要があります。MathContextRoundingMode

これがあなたの場合です:

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

divideまたは、スケールと丸めモードの受け渡しを呼び出します。

BigDecimal bd3 = bd1.divide(bd2, RoundingMode.HALF_UP);
于 2012-05-15T15:11:58.717 に答える
4

ここに問題があります

bd1.divide(bd2)

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

于 2012-05-15T15:11:53.180 に答える
4

この問題は、繰り返し小数になる演算 (除算) が原因で発生します。

解決策は、除算を実行するときにスケールを指定することです。次に例を示します。

BigDecimal one = new BigDecimal("1");
BigDecimal three = new BigDecimal("3");
BigDecimal oneDivThree = one.divide(three, 200, RoundingMode.HALF_UP);
于 2012-05-15T15:17:14.740 に答える
2

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

于 2012-05-15T15:12:50.377 に答える
2

除算が原因で、このエラーが発生しています。

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

これを防ぐには、除算メソッド内でスケールと丸めモードを指定します (BigDecimals の作成時に行ったように)。

ここから撮影。ワーキングディビジョンのサンプルコードも提供されています。

参照: BigDecimal の Java ドキュメント

于 2012-05-15T15:11:14.880 に答える
0

修正するには、次のように 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);
于 2012-05-15T15:17:18.453 に答える