斐波那契序列计算器python

时间:2017-03-02 10:31:10

标签: python performance recursion fibonacci

嗨我对python很新,并尝试创建一个Fibonacci计算器函数,打印所有值到给定数字,如果输入的数字不在序列中,则它将下一个Fibonacci数字添加到列表中。例如,如果输入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: ")))

我已经设法让它工作,但它非常缓慢(我假设由于递归)无论如何我可以加速它而不会大规模改变程序?

3 个答案:

答案 0 :(得分: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,[])初始化它。在每次迭代中,它将计算下一个Fibonacci数c = a+b并将其附加到result。如果该数字仍然小于c < 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: ")))

答案 1 :(得分:0)

这使用递归但比天真的递归实现快得多

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]] 

答案 2 :(得分:0)

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

"""
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}")