私はBigDecimalでexpを呼びたいと思っていますが、BigDecimalはこの関数を直接サポートしていないようです。どのようにこの目標を達成できますか?スカラーのBigDecimalで関数のexpを達成するには?
答えて
何か:
def etox(x: BigDecimal, p: Int) =
Stream.from(1).takeWhile(_ <= p)
.foldLeft((BigDecimal(1), BigDecimal(1)) -> BigDecimal(1)) {
case (((fac, pow), res), n) =>
val f = fac * n
val p = pow * x
((f, p), res + p/f)
}._2
は、それがe^xのテイラー級数の最初のp
メンバーを合計します。テイラー級数はかなり早く収束するので、これは比較的小さなp
の値でもかなり良い精度を与えるはずです。 etox(1, 20)
は、例えば、Math.E
(new BigDecimal(Math.E).pow(1)
〜70マイクロ秒)よりもはるかに良い(約100マイクロ秒で)18桁の数字を取得します。
p
を調整することで、精度と速度を制御できます。 私のラップトップのetox(1938435340345L, 1000)
は約50ミリ秒かかりますが、etox(1938435340345L, 10000)
は17.5秒かかっています。
x
の値が大きいほど、適切な精度を得る必要があることに注意してください。p
x=1
の場合は、前述のようにp=20
で十分ですが、x=25
の場合は、.pow
の精度を超えるには、100
になるようにp
が必要です。
なぜこれが線形ではないのだろうと思います。 etox(1, 100).pow(25)
:高いx
値のための妥協案として、これらの巨大な階乗を計算するのに必要な作業をしなければならない、そしてそれは、それらを表現するために要するメモリをgc'ing ...
しなければならない、あなたのような何かを行うことができます。これにより、ほぼ同じ時間にetox(25, 100)
よりも精度が向上します。 BigDecimal(Math.E).pow(100)
は64マイクロ秒かかり、正確に最初の14桁を計算します。 etox(1, 1000).pow(100)
は1.4ミリ秒かかり、33桁目まで正確です。
更新は、実際に、etox(100, 1000)
は私が推測する、... 1.1ミリ秒で正しく34桁の数字を取得しますので、それを使用して形成されていない問題ですべてのことくらい。私はその差がもっと大きいと考えています。x
たとえばetox(1000, 1000)
はオフですが、etox(1, 1000).pow(1000)
はまだかなり良いです。
math.exp(myDecimal.toDouble)
二重エンコーディングによる精度の低下があります。多分このような
これを参照してください:http://stackoverflow.com/questions/11855775/bigdecimal-eulers-number-calculation-to-emulate-math-expdouble-a –