【问题标题】:Fibonacci sequence calculator python斐波那契数列计算器python
【发布时间】:2017-07-22 00:43:03
【问题描述】:

您好,我是 python 的新手,我尝试创建一个斐波那契计算器函数,该函数可以打印到给定数字的所有值,如果输入的数字不在序列中,那么它将下一个斐波那契数字添加到列表中。例如,如果输入 10,它应该返回 [0, 1, 1, 2, 3, 5, 8, 13]。该函数必须是递归的。这是我当前的代码:

def fibonacci(n):
    n = int(n)
    # The nested sub_fib function computes the Fibonacci sequence

    def sub_fib(n):
        if n < 2:
            return n
        else:
            return (sub_fib(n-1) + sub_fib(n-2))

    #This aspect of the main fib function applies the condition if the number
    # input is not in the sequence then it returns the next value up

    fib_seq= [sub_fib(i) for i in range(0,n) if sub_fib(i)<=n]
    if fib_seq[-1] < n:
        fib_seq.append(fib_seq[-1] + fib_seq[-2])
        return fib_seq
    else:
        return fib_seq
print(fibonacci(input("Input a number to print sequence up to: ")))

我已经设法让它工作,但它非常慢(我假设是由于递归)无论如何我可以在不大规模更改程序的情况下加快它的速度吗?

【问题讨论】:

  • 那是因为它是递归的,不使用记忆...递归真的是一个要求吗?
  • @WillemVanOnsem,无需记忆 - 足以将 sub_fib 重新定义为生成器。
  • @volcano:在这种情况下,让它递归是非常没用的。
  • @WillemVanOnsem,哎呀,错过了这一点

标签: python performance recursion fibonacci


【解决方案1】:

程序运行缓慢的两个主要原因:

  • 分别计算每个斐波那契数,您不会重复使用您为查找前一个数所付出的努力;
  • 您计算前 n 个斐波那契数,但从 条件失败的那一刻起,您可以停止

您可以将程序更改为仍然是递归的,但重用计算前一个数字的工作,并从您构建列表的那一刻起停止。

您只需使用以下函数:

def fibon(a,b,n,result):
    c = a+b
    result.append(c)
    if c < n:
        fibon(b,c,n,result)
    return result

我们将其初始化为:fibon(0,1,n,[])。在每次迭代中,它将计算下一个斐波那契数 c = a+b 并将其附加到 result。如果这个数字仍然小于c &lt; n,那么我们需要计算下一个数字,从而执行递归调用。

def fibonacci(n):
    n = int(n)

    def fibon(a,b,n,result):
        c = a+b
        result.append(c)
        if c < n:
            fibon(b,c,n,result)
        return result

    return fibon(0,1,n,[])

print(fibonacci(input("Input a number to print sequence up to: ")))

【讨论】:

  • 所以你用 fibon(0,1,n,[]) 初始化它,然后每次调用 a,b 的值,因此 c 被之前的值更新,直到 c 不小于 n?它工作得很好,我只是想在继续之前确保我理解它。
  • @Boogieboots:确实。
【解决方案2】:

这使用递归,但比简单的递归实现要快得多

def fib(n):
    if n == 1:
        return [1]
    elif n == 2:
        return [1, 1]
    else:
        sub = fib(n - 1)
        return sub + [sub[-1] + sub[-2]] 

【讨论】:

    【解决方案3】:

    以下是一些如何提高速度的示例:

    """
    Performance calculation for recursion, memoization, tabulation and generator
    
    fib took: 27.052446
    mem_fib took: 0.000134
    tabular_fib took: 0.000175
    yield_fib took: 0.000033
    """
    from timeit import timeit
    
    
    LOOKUP_SIZE = 100
    number = 30
    lookup = [None] * LOOKUP_SIZE
    
    
    def fib(n):
        return 1 if n <= 2 else fib(n - 1) + fib(n - 2)
    
    
    def mem_fib(n):
        """Using memoization."""
        if n <= 2:
            return 1
        if lookup[n] is None:
            lookup[n] = mem_fib(n - 1) + mem_fib(n - 2)
    
        return lookup[n]
    
    
    def tabular_fib(n):
        """Using Tabulation."""
        results = [1, 1]
        for i in range(2, n):
            results.append(results[i - 1] + results[i - 2])
        return results[-1]
    
    
    def yield_fib(n):
        """Using generator."""
        a = b = 1
        yield a
        yield b
        while n > 2:
            n -= 1
            a, b = b, a + b
            yield b
    
    
    for f in [fib, mem_fib, tabular_fib, yield_fib]:
        t = timeit(stmt=f"f({number})", number=10, globals=globals())
        print(f"{f.__name__} took: {t:.6f}")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-18
      • 2013-03-31
      • 2016-12-11
      • 2016-08-04
      • 2013-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多