How to write the Fibonacci Sequence?

前端 未结 30 2361
醉酒成梦
醉酒成梦 2020-11-22 00:32

I had originally coded the program wrongly. Instead of returning the Fibonacci numbers between a range (ie. startNumber 1, endNumber 20 should = only those numbers between 1

相关标签:
30条回答
  • 2020-11-22 01:18

    Efficient Pythonic generator of the Fibonacci sequence

    I found this question while trying to get the shortest Pythonic generation of this sequence (later realizing I had seen a similar one in a Python Enhancement Proposal), and I haven't noticed anyone else coming up with my specific solution (although the top answer gets close, but still less elegant), so here it is, with comments describing the first iteration, because I think that may help readers understand:

    def fib():
        a, b = 0, 1
        while True:            # First iteration:
            yield a            # yield 0 to start with and then
            a, b = b, a + b    # a will now be 1, and b will also be 1, (0 + 1)
    

    and usage:

    for index, fibonacci_number in zip(range(10), fib()):
         print('{i:3}: {f:3}'.format(i=index, f=fibonacci_number))
    

    prints:

      0:   0
      1:   1
      2:   1
      3:   2
      4:   3
      5:   5
      6:   8
      7:  13
      8:  21
      9:  34
     10:  55
    

    (For attribution purposes, I recently noticed a similar implementation in the Python documentation on modules, even using the variables a and b, which I now recall having seen before writing this answer. But I think this answer demonstrates better usage of the language.)

    Recursively defined implementation

    The Online Encyclopedia of Integer Sequences defines the Fibonacci Sequence recursively as

    F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1

    Succinctly defining this recursively in Python can be done as follows:

    def rec_fib(n):
        '''inefficient recursive function as defined, returns Fibonacci number'''
        if n > 1:
            return rec_fib(n-1) + rec_fib(n-2)
        return n
    

    But this exact representation of the mathematical definition is incredibly inefficient for numbers much greater than 30, because each number being calculated must also calculate for every number below it. You can demonstrate how slow it is by using the following:

    for i in range(40):
        print(i, rec_fib(i))
    

    Memoized recursion for efficiency

    It can be memoized to improve speed (this example takes advantage of the fact that a default keyword argument is the same object every time the function is called, but normally you wouldn't use a mutable default argument for exactly this reason):

    def mem_fib(n, _cache={}):
        '''efficiently memoized recursive function, returns a Fibonacci number'''
        if n in _cache:
            return _cache[n]
        elif n > 1:
            return _cache.setdefault(n, mem_fib(n-1) + mem_fib(n-2))
        return n
    

    You'll find the memoized version is much faster, and will quickly exceed your maximum recursion depth before you can even think to get up for coffee. You can see how much faster it is visually by doing this:

    for i in range(40):
        print(i, mem_fib(i))
    

    (It may seem like we can just do the below, but it actually doesn't let us take advantage of the cache, because it calls itself before setdefault is called.)

    def mem_fib(n, _cache={}):
        '''don't do this'''
        if n > 1:  
            return _cache.setdefault(n, mem_fib(n-1) + mem_fib(n-2))
        return n
    

    Recursively defined generator:

    As I have been learning Haskell, I came across this implementation in Haskell:

    fib@(0:tfib) = 0:1: zipWith (+) fib tfib
    

    The closest I think I can get to this in Python at the moment is:

    from itertools import tee
    
    def fib():
        yield 0
        yield 1
        # tee required, else with two fib()'s algorithm becomes quadratic
        f, tf = tee(fib()) 
        next(tf)
        for a, b in zip(f, tf):
            yield a + b
    

    This demonstrates it:

    [f for _, f in zip(range(999), fib())]
    

    It can only go up to the recursion limit, though. Usually, 1000, whereas the Haskell version can go up to the 100s of millions, although it uses all 8 GB of my laptop's memory to do so:

    > length $ take 100000000 fib 
    100000000
    

    Consuming the iterator to get the nth fibonacci number

    A commenter asks:

    Question for the Fib() function which is based on iterator: what if you want to get the nth, for instance 10th fib number?

    The itertools documentation has a recipe for this:

    from itertools import islice
    
    def nth(iterable, n, default=None):
        "Returns the nth item or a default value"
        return next(islice(iterable, n, None), default)
    

    and now:

    >>> nth(fib(), 10)
    55
    
    0 讨论(0)
  • 2020-11-22 01:19

    Time complexity :

    The caching feature reduces the normal way of calculating Fibonacci series from O(2^n) to O(n) by eliminating the repeats in the recursive tree of Fibonacci series :

    enter image description here

    Code :

    import sys
    
    table = [0]*1000
    
    def FastFib(n):
        if n<=1:
            return n
        else:
            if(table[n-1]==0):
                table[n-1] = FastFib(n-1)
            if(table[n-2]==0):
                table[n-2] = FastFib(n-2)
            table[n] = table[n-1] + table[n-2]
            return table[n]
    
    def main():
        print('Enter a number : ')
        num = int(sys.stdin.readline())
        print(FastFib(num))
    
    if __name__=='__main__':
        main()
    
    0 讨论(0)
  • 2020-11-22 01:19

    15 minutes into a tutorial I used when learning Python, it asked the reader to write a program that would calculate a Fibonacci sequence from 3 input numbers (first Fibonacci number, second number, and number at which to stop the sequence). The tutorial had only covered variables, if/thens, and loops up to that point. No functions yet. I came up with the following code:

    sum = 0
    endingnumber = 1                
    
    print "\n.:Fibonacci sequence:.\n"
    
    firstnumber = input("Enter the first number: ")
    secondnumber = input("Enter the second number: ")
    endingnumber = input("Enter the number to stop at: ")
    
    if secondnumber < firstnumber:
    
        print "\nSecond number must be bigger than the first number!!!\n"
    
    else:
    
    while sum <= endingnumber:
    
        print firstnumber
    
        if secondnumber > endingnumber:
    
            break
    
        else:
    
            print secondnumber
            sum = firstnumber + secondnumber
            firstnumber = sum
            secondnumber = secondnumber + sum
    

    As you can see, it's really inefficient, but it DOES work.

    0 讨论(0)
  • 2020-11-22 01:19

    Just going through http://projecteuler.net/problem=2 this was my take on it

    # Even Fibonacci numbers
    # Problem 2
    
    def get_fibonacci(size):
        numbers = [1,2]
        while size > len(numbers):
            next_fibonacci = numbers[-1]+numbers[-2]
            numbers.append(next_fibonacci)
    
        print numbers
    
    get_fibonacci(20)
    
    0 讨论(0)
  • 2020-11-22 01:20
    def fib():
        a,b = 1,1
        num=eval(input("Please input what Fib number you want to be calculated: "))
        num_int=int(num-2)
        for i in range (num_int):
            a,b=b,a+b
        print(b)
    
    0 讨论(0)
  • 2020-11-22 01:20

    based on classic fibonacci sequence and just for the sake of the one-liners

    if you just need the number of the index, you can use the reduce (even if reduce it's not best suited for this it can be a good exercise)

    def fibonacci(index):
        return reduce(lambda r,v: r.append(r[-1]+r[-2]) or (r.pop(0) and 0) or r , xrange(index), [0, 1])[1]
    

    and to get the complete array just remove the or (r.pop(0) and 0)

    reduce(lambda r,v: r.append(r[-1]+r[-2]) or r , xrange(last_index), [0, 1])
    
    0 讨论(0)
提交回复
热议问题