Python mpmath 不是任意精度?
我在继续之前的问题,想用贝内特算法计算斐波那契数。为了处理任意精度的计算,我找到了 mpmath
这个库。不过在计算到某个值的时候,似乎出现了问题。例如,计算第99个斐波那契数时,结果是:
218922995834555891712
但这个结果应该是(参考链接:这里):
218922995834555169026
这是我的代码:
from mpmath import * def Phi(): return (1 + sqrt(5)) / 2 def phi(): return (1 - sqrt(5)) / 2 def F(n): return (power(Phi(), n) - power(phi(), n)) / sqrt(5) start = 99 end = 100 for x in range(start, end): print(x, int(F(x)))
3 个回答
3
其实,mpmath的默认精度是15,这个精度我觉得不够,如果你想要得到21位数字的结果的话。
你可以做的一件事就是把精度设置得更高,然后使用mpmath提供的加法、减法等运算功能。
from mpmath import mp
mp.dps = 50
sqrt5 = mp.sqrt(5)
def Phi():
return 0.5*mp.fadd(1, sqrt5)
def phi():
return 0.5*mp.fsub(1, sqrt5)
def F(n):
return mp.fdiv(mp.power(Phi(), n) - mp.power(phi(), n), sqrt5)
print int(F(99))
这样你就能得到
218922995834555169026L
4
mpmath 是一个可以进行任意精度数学运算的工具,如果你使用它的任意精度数学模块,而不是默认的设置,它可以做到非常准确。
mpmath 有多个模块可以选择,这些模块会影响结果的准确性和计算速度,你可以根据自己的需求来选择。默认情况下,它使用的是 Python 的浮点数,这就是你之前看到的结果。
如果你调用 mpmath 的 fib( ) 函数,并且把 mp.dps 设置得足够高,你就能得到上面提到的正确答案。
>>> from mpmath import mp
>>> mp.dps = 25
>>> mp.nprint( mp.fib( 99 ), 25 )
218922995834555169026.0
>>> mp.nprint( mpmath.fib( 99 ), 25 )
218922995834555169026.0
但是,如果你不使用 mp 模块,你得到的结果就只能和 Python 的双精度浮点数一样准确。
>>> import mpmath
>>> mpmath.dps = 25
>>> mpmath.nprint( mpmath.fib( 99 ), 25
218922995834555170816.0
3
mpmath
是一个可以进行任意精度计算的工具(精度可以通过 mpmath.mp.dps
来设置),但它的计算结果可能不够准确。例如,mpmath.sqrt(5)
的结果并不准确,因此基于这个结果进行的任何计算也会不准确。
如果想要得到准确的 sqrt(5)
的结果,你需要使用一个支持抽象计算的库,比如 http://sympy.org/。
想要准确计算斐波那契数列,最简单的方法可能是使用只进行整数运算的算法。例如:
def fib(n):
if n < 0:
raise ValueError
def fib_rec(n):
if n == 0:
return 0, 1
else:
a, b = fib_rec(n >> 1)
c = a * ((b << 1) - a)
d = b * b + a * a
if n & 1:
return d, c + d
else:
return c, d
return fib_rec(n)[0]