简体   繁体   English

斐波那契序列计算器python

[英]Fibonacci sequence calculator python

Hi I'm fairly new to python and trying to create a Fibonacci calculator function that prints all values up to a given number, if the number entered is not in the sequence then it adds the next Fibonacci number to the list. 嗨,我是python的新手,尝试创建一个Fibonacci计算器函数,该函数将所有值打印到给定的数字,如果输入的数字不在序列中,则它将下一个Fibonacci数字添加到列表中。 For example, if 10 is entered it should return [0, 1, 1, 2, 3, 5, 8, 13] . 例如,如果输入10,则应返回[0, 1, 1, 2, 3, 5, 8, 13] The function has to be recursive. 该函数必须是递归的。 Here is my current code: 这是我当前的代码:

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

I've managed to get it to work but it is incredibly slow (I assume due to the recursion) is there anyway I can speed it up without massively changing the program? 我设法使其正常工作,但它的运行速度极其慢(我认为是由于递归),有什么办法可以在不进行大量更改的情况下加快速度吗?

The two main reasons why your program is slow: 您的程序运行缓慢的两个主要原因:

  • you calculate each Fibonacci number separately , you do not reuse the effort you have invested in finding the previous number; 单独计算每个Fibonacci数,你不重用你投资在寻找上一个数字的努力;
  • you calculate the first n Fibonacci numbers, but from the moment the condition fails, you can stop . 您可以计算前n个斐波那契数,但是从条件失败的那一刻起,您可以停止

You can change the program to still be recursive, but reuse the work to compute the previous number, and stop from the moment you have constructed the list. 您可以将程序更改为递归,但可以重复使用工作来计算先前的数字,并从构造列表的那一刻起停止。

You simply have to use the following function: 您只需要使用以下功能:

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

and we initialize it with: fibon(0,1,n,[]) . 然后用以下fibon(0,1,n,[])初始化它: fibon(0,1,n,[]) In each iteration, it will calculate the next Fibonacci number c = a+b and append it to the result . 在每次迭代中,它将计算下一个斐波那契数c = a+b并将其附加到result In case that number is still smaller than c < n then we need to calculate the next number and thus perform the recursive call. 如果该数字仍然小于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: ")))

This uses recursion but much faster than naive recursive implementations 这使用了递归,但是比幼稚的递归实现要快得多

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

Here are some examples of how you can improve the speed: 以下是一些如何提高速度的示例:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM