我几天前写过这篇文章似乎工作得很好,但速度很慢。在斐波那契序列中生成第100百万个数字需要25秒。有没有办法提高效率?
def main():
num1 = 0
num2 = 1
var = 0
num = int(raw_input("What fibonacci number do you want to know? "))
while 1:
num3 = num1
num1 = num1 + num2
num2 = num3
var+=1
if var>=num:
print num3
return main()
else:
None
main()
请注意,我是python的初学者,所以我不会理解高级概念
答案 0 :(得分:4)
我发现使用卢卡斯数字给我的结果紧固:
def powLF(n):
if n == 1: return (1, 1)
L, F = powLF(n//2)
L, F = (L**2 + 5*F**2) >> 1, L*F
if n & 1:
return ((L + 5*F)>>1, (L + F) >>1)
else:
return (L, F)
def fib(n):
if n & 1:
return powLF(n)[1]
else:
L, F = powLF(n // 2)
return L * F
与矩阵指数一样,它具有O(NlogN)复杂度,但它的常数成本较低,因此在“点数”上击败它:
>>> timeit.timeit('fib(1000)', 'from __main__ import fibM as fib', number=10000)
0.40711593627929688
>>> timeit.timeit('fib(1000)', 'from __main__ import fibL as fib', number=10000)
0.20211100578308105
是的,这是两倍的速度。
我不能赞同上面的实现,也没有把它与之比较的矩阵指数算法;两者都列在literateprograms.org上。
计算第1,000,000个Fibonacci数:
>>> timeit.timeit('fib(1000000)', 'from __main__ import fib', number=100)/100
0.09112384080886841
不到十分之一秒。
答案 1 :(得分:2)
不是严格意义上的答案,但新程序员的一个非常普遍的习惯是违反了Separation of Concerns。
好多了:
def fibonacci(n):
...
def main():
num = int(raw_input("What fibonacci number do you want to know? "))
print fibonacci(num)
让fibonacci不会被用户界面代码弄得乱七八糟。
答案 2 :(得分:1)
您可以使用matrix exponention,这是在O(logn)
整数运算中完成的,或者使用closed form expression,这是以幂函数的速度完成的。 (请注意numerical errors使用封闭式表达式)。
答案 3 :(得分:1)
如果要快速计算斐波纳契数,则应使用闭合表达式或矩阵求幂。 如果您希望能够生成任意大数,则使用矩阵求幂。
示例实现:
>>> def matrix_mul(A, B):
... return ([A[0][0] * B[0][0] + A[0][1] * B[1][0],
... A[0][0] * B[0][1] + A[0][1] * B[1][1]],
... [A[1][0] * B[0][0] + A[1][1] * B[1][0],
... A[1][0] * B[0][1] + A[1][1] * B[1][1]])
...
>>> def matrix_exp(A, e):
... if not e:
... return [[1,0],[0,1]]
... elif e % 2:
... return matrix_mul(A, matrix_exp(A, e-1))
... else:
... sq= matrix_exp(A, e//2)
... return matrix_mul(sq, sq)
...
>>> def fibo(n):
... M = [[1,1],[1,0]]
... return matrix_exp(M, n)[0][0]
>>> fibo(1)
1
>>> fibo(2)
2
>>> fibo(3)
3
>>> fibo(4)
5
>>> fibo(5)
8
>>> fibo(115)
781774079430987230203437L
>>> fibo(123456)
#instantaneus output of a HUGE number
还有这个不可读的版本,速度要快得多:
>>> fibs = {0: 0, 1: 1}
>>> def fib(n):
... if n in fibs: return fibs[n]
... if n % 2 == 0:
... fibs[n] = ((2 * fib((n / 2) - 1)) + fib(n / 2)) * fib(n / 2)
... return fibs[n]
... else:
... fibs[n] = (fib((n - 1) / 2) ** 2) + (fib((n+1) / 2) ** 2)
... return fibs[n]
...
>>> timeit.timeit('fib(1000000)', 'from __main__ import fib', number=100)/100
0.0012753009796142578 # 1 millisecond for the millionth fibonacci number :O
这是literateprograms.org的最后一个(在另一个答案中链接)。
答案 4 :(得分:0)
这非常有效:
import numpy as np
M = np.matrix([[1, 1], [1, 0]])
def fib(n):
if n < 2:
return 1
MProd = M.copy()
for _ in xrange(n-2):
MProd *= M
return MProd[0,0] + MProd[0,1]