我想在BigDecimal上调用exp,而BigDecimal似乎不直接支持这个函数。我怎样才能实现这个目标?
答案 0 :(得分:1)
math.exp(myDecimal.toDouble)
由于双重编码而导致精度下降。
答案 1 :(得分:0)
这样的事情可能是:
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
它总结了泰勒系列的第一个p
成员e ^ x。泰勒级数很快收敛,所以即使值p
相对较小,这也应该给你一个相当好的精度。例如,etox(1, 20)
得到18位数(大约100微秒),这已经比Math.E
(new BigDecimal(Math.E).pow(1)
需要大约70微秒)好了。
您可以通过调整p
来控制精度与速度。
在我的笔记本电脑上etox(1938435340345L, 1000)
需要大约50毫秒,而etox(1938435340345L, 10000)
需要17.5秒。
请注意,x
的值越高,获得足够精度所需的p
越大。例如,对于x=1
,p=20
就足够了,正如我之前提到的那样,但如果x=25
,那么您需要p
至少100
才能击败.pow
精度。
我想知道,为什么这不是线性的。必须与所涉及的工作有关,以计算那些巨大的阶乘,以及代表它们的gc记忆...
作为较高x
值的折衷方案,您可以执行以下操作:
etox(1, 100).pow(25)
。这使您在大约相同的时间内比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)
仍然相当不错。