我试图更好地理解递归和缓存,但我仍然取得了有趣的进展(有时候我有点慢)。我在理解这段代码时遇到小问题:
# Fibonacci recursive with result storage
class FibonacciStorage:
_storage = { 0:1, 1:1 }
@staticmethod
def _fib(number):
try: # is this already calculated
return FibonacciStorage._storage[number] #searches dict, and if value exists then return it
except KeyError:
result = FibonacciStorage._fib(number-1) + FibonacciStorage._fib(number-2) #this is the actual Fibonacci Formula
FibonacciStorage._storage[number] = result #adds result to dictionary
#print FibonacciStorage._storage #this shows the storage list growing with each iteration.
return result
@staticmethod
def fib(number): #first function, it has two asserts to basically make sure number is whole/positive and if its okay passes it to _fib(where the real work is done)
# only do the assert statements once
assert(isinstance(number,int)),"Needs a whole number"
assert(number>0),"Needs a positive whole number"
return FibonacciStorage._fib(number)
# use a more readable name
getFib = FibonacciStorage.fib
print getFib(50)
我在网上找到了这段代码,并试图评论每一行,以了解它实际上在做什么。我不明白这是一个递归,它会循环遍历代码,直到给出正确的结果,但我不知道它是如何调用自己的。
我认为这是第一行:result = FibonacciStorage._fib(number-1) + FibonacciStorage._fib(number-2)
但我很困惑,因为我的print FibonacciStorage._storage
行显示存储缓存增长和增长,但它下面的行是返回函数。我怀疑我不明白return result
实际上是如何以某种方式再次触发递归。
我也不确定存储字典是如何让这个程序变得如此之快。我对fib序列的简单递归需要很长时间(即使我保存数据),但在这种情况下,如果你做了print getFib(200)
它的瞬间。缓存如何使它如此之快?
总而言之,有两个问题:
1)如何实际触发递归?如果在每个循环中访问我的print语句?
2)缓存如何比其他纤维序列加速?类结构或@static方法有所不同吗?例如,这似乎是即时的http://en.literateprograms.org/Fibonacci_numbers_(Python)稍有延迟。
3)也许还有一点兴趣,一个fibnocci类型的算法规模(分开并且并行运行)只是出于兴趣还是仅限于一个过程?
任何见解都会有所帮助。
答案 0 :(得分:5)
(1)递归调用就在这一行:
result = FibonacciStorage._fib(number-1) + FibonacciStorage._fib(number-2)
// here ^ and here ^
你是对的,这是"实际的Fibonacci公式",根据定义是递归的。
(2)缓存正在极大地加快速度。有什么不同的是持久对象_storage
,它可以为您节省大量的重复工作量。壮观。考虑:
fib(4)
/ \
fib(3) + fib(2)
/ \ / \
fib(2) + fib(1) fib(1) + fib(0)
/ \
fib(1) + fib(0)
这只是fib(4)
,您已经可以看到冗余。通过简单地缓存fib(3)
和fib(4)
的整数值,您可以将fib(5)
所需的计算次数从7减少到1.并且只有当您更高时才会节省成本
答案 1 :(得分:2)
问题中的斐波那契实现使用一种名为memoization的技术来存储已经计算过的值,并在每次需要时有效地检索它们,而不是重新计算它们。这具有巨大的性能优势,因为值只需要计算一次。
关于您的问题:
答案 2 :(得分:1)
很高兴知道Python dicts有一个__missing__
方法,用于丢失密钥:
class FibonacciStorage(dict):
def __missing__(self, n):
self[n] = self[n - 1] + self[n - 2]
return self[n]
用法:
fib = FibonacciStorage({0: 1, 1: 1})
print(fib[50]) #20365011074