不了解这种递归的Fibonacci实现

时间:2018-05-26 18:54:59

标签: python python-3.x recursion fibonacci

这不是我的代码。我无法理解第3行正是做什么,逻辑运算。

cache = {}
def fiba(n):
     cache[n] = cache.get(n, 0) or (n <= 1 and 1 or fiba(n-1) + fiba(n-2))
     return cache[n]

n = 0
x = 0
while fiba(x) <= 4000000:
       if not fiba(x) % 2: n = n + fiba(x)
       x=x+1
print(n)

3 个答案:

答案 0 :(得分:0)

第3行 如果n为零,则看起来条件语句的第一部分返回零。第二部分是返回序列中的一个或下一个斐波纳契数。所有这些都存储在缓存中(实际上只是一个数组)。

答案 1 :(得分:0)

这就是这个:

result = cache.get(n, 0)
if not result:  # i.e. if result == 0:
    if n <= 1:
        result = 1
    else:
        result = fiba(n - 1) + fiba(n - 2)
cache[n] = result

请参阅docs on boolean operators以更好地了解他们的行为。

答案 2 :(得分:0)

在我看来,尝试通过缓存先前的计算来提高递归算法的效率。在最简单的递归Fibonacci中,你只需要

def fiba(n):
    return (n<=1 and 1) or fiba(n-1) + fiba(n-1)

这是

的简写
if(n<=1)
    return 1
else 
    return fiba(n-1)+fiba(n-2)    

对于n = 0,将返回1,对于n = 1将返回1,然后在此之后为所有n返回下一个斐波纳契数(以前两个的总和计算)。

如果我们仔细检查此代码,我们会看到计算fiba(4)调用fiba(3)fiba(2),后者又调用fiba(2)fiba(1),{{分别为1}}和fiba(1)。请注意,我们多次调用fiba(0),并且因为它本身是递归函数,所以这可能会变得昂贵,特别是对于较大的数字,因为函数调用的数量在每个级别呈指数增长。因此,我们的想法是只计算每个fiba(2)一次,然后将其存储在内存中(fiba(n)),以便下次我们需要它时,我们可以简单地查找它而不是重新计算它。

你问的问题是大部分工作是什么。我们将cache斐波那契数存储在缓存的索引n。条件从左到右进行评估:首先[n]看看我们是否已经计算了数字,如果是,则返回它。参数中的0表示如果密钥cache.get(n,0)不存在,则缓存将返回n而不是0。这不是必需的,因为0或None将导致None条件的另一侧被评估。

简而言之,or检查是否已经计算了值,如果没有,我们会转到cache.get(n,0)的另一半。这会像我们在没有缓存的函数中那样计算or数字,或者通过n的基本情况或者通过对前两个值求和来计算。