[英]Issue when computing fibonacci number with recursion in python
我有這段代碼用於使用緩存(字典)計算斐波那契數。
cache = {}
def dynamic_fib(n):
print n
if n == 0 or n == 1:
return 1
if not (n in cache):
print "caching %d" % n
cache[n] = dynamic_fib(n-1) + dynamic_fib(n-2)
return cache[n]
if __name__ == "__main__":
start = time.time()
print "DYNAMIC: ", dynamic_fib(2000)
print (time.time() - start)
我可以使用較小的數字來正常工作,但是輸入超過1000則似乎停止了。
這是將2000作為輸入的結果。
....
caching 1008
1007
caching 1007
1006
caching 1006
1005
caching 1005
這是將1000作為輸入的結果。
....
8
caching 8
7
caching 7
6
caching 6
5
caching 5
看起來像是將995存儲到字典中之后,它就掛了。 這可能有什么問題? 我可以使用哪種調試技術來查看python出了什么問題?
我在Mac OS X 10.7.5上運行python,我有4G字節的RAM,所以我認為一些KB(甚至MB)的內存使用沒有太大關系。
Python的默認遞歸限制設置為1000。您需要在程序中增加它。
import sys
sys.setrecursionlimit(5000)
來自: http : //docs.python.org/2/library/sys.html#sys.setrecursionlimit
sys.setrecursionlimit(限制)
Set the maximum depth of the Python interpreter stack to limit. This limit prevents infinite recursion from causing an overflow of the C stack and crashing Python. The highest possible limit is platform-dependent. A user may need to set the limit higher when she has a program that requires deep recursion and a platform that supports a higher limit. This should bedone with care, because a too-high limit can lead to a crash.
通過將緩存存儲為字典,實際上並不會獲得任何好處,因為要計算f(n)
您需要知道f(n-1)
(和f(n-2)
)。 換句話說,您的字典將始終具有從2-n開始的鍵。 您也可以只使用一個列表(它只是一個額外的2個元素)。 這是一個可以正確緩存且未達到遞歸限制(永遠)的版本:
import time
cache = [1,1]
def dynamic_fib(n):
#print n
if n >= len(cache):
for i in range(len(cache),n):
dynamic_fib(i)
cache.append(dynamic_fib(n-1) + dynamic_fib(n-2))
print "caching %d" % n
return cache[n]
if __name__ == "__main__":
start = time.time()
a = dynamic_fib(4000)
print "Dynamic",a
print (time.time() - start)
請注意,使用dict可以完成相同的操作,但是我幾乎肯定列表會更快。
只是為了好玩,這里有很多選擇(以及時間安排!):
def fib_iter(n):
a, b = 1, 1
for i in xrange(n):
a, b = b, a + b
return a
memo_iter = [1,1]
def fib_iter_memo(n):
if n == 0:
return 1
else:
try:
return memo_iter[n+1]
except IndexError:
a,b = memo_iter[-2:]
for i in xrange(len(memo_iter),n+2):
a, b = b, a + b
memo_iter.append(a)
return memo_iter[-1]
dyn_cache = [1,1]
def dynamic_fib(n):
if n >= len(dyn_cache):
for i in xrange(len(dyn_cache),n):
dynamic_fib(i)
dyn_cache.append(dynamic_fib(n-1) + dynamic_fib(n-2))
return dyn_cache[n]
dyn_cache2 = [1,1]
def dynamic_fib2(n):
if n >= len(dyn_cache2):
for i in xrange(len(dyn_cache2),n):
dynamic_fib2(i)
dyn_cache2.append(dyn_cache2[-1] + dyn_cache2[-2])
return dyn_cache2[n]
cache_fibo = [1,1]
def dyn_fib_simple(n):
while len(cache_fibo) <= n:
cache_fibo.append(cache_fibo[-1]+cache_fibo[-2])
return cache_fibo[n]
import timeit
for func in ('dyn_fib_simple','dynamic_fib2','dynamic_fib','fib_iter_memo','fib_iter'):
print timeit.timeit('%s(100)'%func,setup='from __main__ import %s'%func),func
print fib_iter(100)
print fib_iter_memo(100)
print fib_iter_memo(100)
print dynamic_fib(100)
print dynamic_fib2(100)
print dyn_fib_simple(100)
結果:
0.269892930984 dyn_fib_simple
0.256865024567 dynamic_fib2
0.241492033005 dynamic_fib
0.222282171249 fib_iter_memo
7.23831701279 fib_iter
573147844013817084101
573147844013817084101
573147844013817084101
573147844013817084101
573147844013817084101
573147844013817084101
免費版本:
def fibo(n):
cache=[1,1]
while len(cache) < n:
cache.append(cache[-1]+cache[-2])
return cache
這可能是由於堆棧深度的限制,導致RuntimeError。 您可以通過調用來增加堆棧的遞歸限制
sys.setrecursionlimit(<number>)
sys模塊的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.