我试图继续上一个问题,我试图用Benet算法计算斐波纳契数。为了处理任意精度,我找到了mpmath
。然而,实施似乎失败超过一定的价值。例如,第99个值给出:
218922995834555891712
这应该是(ref):
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)))
答案 0 :(得分:2)
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 double一样准确的结果。
>>> import mpmath
>>> mpmath.dps = 25
>>> mpmath.nprint( mpmath.fib( 99 ), 25
218922995834555170816.0
答案 1 :(得分:1)
mpmath
提供任意精度(在mpmath.mp.dps
中设置),但仍然是不准确的计算。例如,mpmath.sqrt(5)
不准确,因此基于此的任何计算也都是不准确的。
要获得sqrt(5)
的准确结果,您必须使用支持抽象计算的库,例如http://sympy.org/。
为了获得Fibonacci数的准确结果,可能最简单的方法是使用只进行整数算术的算法。例如:
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]
答案 2 :(得分:0)
实际上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