【问题标题】:Not understanding this recursive Fibonacci implementation不理解这种递归斐波那契实现
【发布时间】:2018-05-26 18:54:59
【问题描述】:

这不是我的代码。我不明白第 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)

【问题讨论】:

  • 我希望编写该代码的人的编程许可证被吊销。
  • x and yx if x else y 相同。这能解释清楚吗?
  • x if x else y 表示如果 x 或/和 y 评估为 true,则 x 评估为 true?
  • @bfontaine 不,不是。如果x 为假如果xy 都为假,x and y or z 可以评估为z

标签: python python-3.x recursion fibonacci


【解决方案1】:

在我看来,这是一种通过缓存以前的计算来提高递归算法效率的尝试。在最简单的递归斐波那契中,您只需

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 的下一个斐波那契数(计算为前 2 的总和)。

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

您要询问的那一行是这项工作的大部分内容。我们将nth 斐波那契数存储在缓存的索引[n] 中。条件是从左到右计算的:首先cache.get(n,0) 看看我们是否已经计算了这个数字,如果是则返回它。参数中的 0 表示如果键 n 不存在,则缓存返回 0 而不是 None。这并不是真正必要的,因为 0 或 None 将导致 or 条件的另一侧被评估。

简而言之,cache.get(n,0) 会检查该值是否已经计算出来,如果没有,我们就转到or 的另一半。这将计算 nth 数字,就像我们在没有缓存的函数中所做的那样,通过 fiba(0)=fiba(1)=1 的基本情况或通过将前两个值相加。

【讨论】:

  • 现在,OP 无需对他的作业进行深入研究就可以睡个好觉了。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    差不多是这样的:

    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 以更好地了解他们的工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-03
      • 2016-06-27
      • 2014-04-02
      • 2017-02-22
      • 2018-03-02
      • 2014-01-16
      相关资源
      最近更新 更多