5

double よりも大きな固定精度で Scala (および/または Java) で計算を実行しようとしています。私は BigDecimals を Scala のデフォルトのMathContextで使用しています。これは精度が 34 です。すべての入力がこの精度を持っていても、数回の計算の後、結果の精度が爆発し始めることがわかりました。

これは、問題を説明していると思われる計算の例です。

import math.BigDecimal

val z40 = BigDecimal(0).setScale(40) // 0E-40
z40.scale                            // 40
z40.precision                        // 1
(1 + z40*z40).precision              // 81

結果は 81 で、 より精度が高くなりz40ます。私の場合、setScale を使用したことはありませんが、計算で非常に大きなスケールのゼロが発生しています。

これは私が望む動作ではありません。精度 34が(1 + z40*z40)必要です。これは、計算が実行されている MathContext の精度です ( z40*z401 に比べて無視できるほど小さいため)。どうすればこの種の算数を取得できますか?

更新:この動作は、Scala 2.9.* と 2.10.* の間で MathContext の処理が変更されたためです。(コミットを指摘してくれた Paul Phillips に感謝します。)このディスカッションも参照してください。

4

3 に答える 3

3

奇妙に思えます。私はあなたのコードを試し、あなたが期待した結果を得ました:

$ scala
Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_10).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import math.BigDecimal
import math.BigDecimal

scala> val z40 = BigDecimal(0).setScale(40)
z40: scala.math.BigDecimal = 0E-40

scala> z40.scale
res0: Int = 40

scala> z40.precision
res1: Int = 1

scala> (1 + z40*z40).precision
res2: Int = 34

scala> _

ご覧のとおり、期待通りです(1+z40*z40).precision34

于 2012-12-31T04:12:09.440 に答える
0

実は最後の行だと思います

(1 + z40*z40).precision

結果を生成します34(ではありません81)。ここでは実際に精度が上がっているとは思いません。

于 2012-12-31T04:10:52.883 に答える
0

BigDecimals の作成方法は次のとおりです。

val z1 = BigDecimal(1, new java.math.MathContext(
  40, java.math.RoundingMode.valueOf(
    scala.math.BigDecimal.RoundingMode.HALF_UP.toString)))

val z40 = BigDecimal(0, new java.math.MathContext(
  40, java.math.RoundingMode.valueOf(
    scala.math.BigDecimal.RoundingMode.HALF_UP.toString)))

精密爆発は見られません。適切な を使用するだけMathContextです。

于 2012-12-31T09:21:45.693 に答える