#!/usr/bin/python """ Calculate the n'th Fibonacci number. Homework for programming python class. """ # ------------------------------------------------ # This one is simple and uses almost no storage space. # However, if called many times it will repeat the whole calculation. def fib1(n): """ Return the n'th Fibonacci number; fib(n)=fib(n-1)+fib(n-2). >>> fib(0) 1 >>> fib(1) 1 >>> fib(2) 2 >>> fib(3) 3 >>> fib(4) 5 >>> fib(5) 8 >>> fib(20) 10946 """ if n < 2 : return 1 # fib(0)=fib(1)=1 else : i = 2 fib_i_minus2 = 1 # initialize the two previous fib's fib_i_minus1 = 1 # walk from i=2 up to i=n while i <= n: # calculate each fib(i) from i=2 to i=n fib_i = fib_i_minus2 + fib_i_minus1 fib_i_minus2 = fib_i_minus1 # . shift everything fib_i_minus1 = fib_i # . up by one i = i + 1 # . return fib_i # ------------------------------------------------ # This one is very tricky - almost magic. # Algorithms like this are called 'recursive'; we'll see 'em later. # However, in this case it's extremely inefficient, # since each fib(n) is calculated many, many times. def fib2(n): """ Recursive version """ if n <= 1: return 1 else: return fib2(n-1) + fib2(n-2) # ------------------------------------------------ # This one is the fastest, I'd expect, if we do many of 'em. # It only calculates each fib(n) once, and remembers # them between calls to the function with a global array. # However, it needs an array as large as the biggest n requested, # and the array grows as needed, which has a time price, too. fibs = [1,1] # initial array of [fib(0), fib(1)] def fib3(n): """ Most efficient version """ if n >= len(fibs): for i in range(len(fibs),n+1): fibs.append( fibs[i-1] + fibs[i-2] ) return fibs[n] # --- timing ---------------------------------------- import os # operating system functions saved_time = [0] def start_timer(): saved_time[0] = os.times()[4] # seconds since system boot def get_elapsed_time(): return os.times()[4] - saved_time[0] # ----------------------------------------------- # Now let's test 'em # # Here I'm getting tricky by putting # the functions and their names into arrays, # and looping over those arrays to test all three versions. numbers = range(25) names = ['fib1', 'fib2', 'fib3'] functions = [fib1, fib2, fib3] for which in range(len(names)): start_timer() for number in numbers: print names[which], '(', number, ')=', functions[which](number) print 'elapsed time = ', get_elapsed_time() print # Turns out that 1 and 3 run at essentially the same speed # until we're doing lots of numbers (which get very big). # # numbers=range(200) # 1 gives elapsed = 0.12 # 2 gives elapsed = 0.06 # # But for small numbers of calls to fib(), 1 is quickest: # it doesn't need to do anything with lists and just blasts away. # The recursive version bogs down relatively soon, # at around n=30; the recursive calls pile up exponentially # and it runs out of memory. """ mdhcp237:Desktop$ python fib.py fib1 ( 0 )= 1 fib1 ( 1 )= 1 fib1 ( 2 )= 2 fib1 ( 3 )= 3 fib1 ( 4 )= 5 fib1 ( 5 )= 8 fib1 ( 6 )= 13 fib1 ( 7 )= 21 fib1 ( 8 )= 34 fib1 ( 9 )= 55 fib1 ( 10 )= 89 fib1 ( 11 )= 144 fib1 ( 12 )= 233 fib1 ( 13 )= 377 fib1 ( 14 )= 610 fib1 ( 15 )= 987 fib1 ( 16 )= 1597 fib1 ( 17 )= 2584 fib1 ( 18 )= 4181 fib1 ( 19 )= 6765 fib1 ( 20 )= 10946 fib1 ( 21 )= 17711 fib1 ( 22 )= 28657 fib1 ( 23 )= 46368 fib1 ( 24 )= 75025 elapsed time = 0.0166666666046 fib2 ( 0 )= 1 fib2 ( 1 )= 1 fib2 ( 2 )= 2 fib2 ( 3 )= 3 fib2 ( 4 )= 5 fib2 ( 5 )= 8 fib2 ( 6 )= 13 fib2 ( 7 )= 21 fib2 ( 8 )= 34 fib2 ( 9 )= 55 fib2 ( 10 )= 89 fib2 ( 11 )= 144 fib2 ( 12 )= 233 fib2 ( 13 )= 377 fib2 ( 14 )= 610 fib2 ( 15 )= 987 fib2 ( 16 )= 1597 fib2 ( 17 )= 2584 fib2 ( 18 )= 4181 fib2 ( 19 )= 6765 fib2 ( 20 )= 10946 fib2 ( 21 )= 17711 fib2 ( 22 )= 28657 fib2 ( 23 )= 46368 fib2 ( 24 )= 75025 elapsed time = 0.716666666791 fib3 ( 0 )= 1 fib3 ( 1 )= 1 fib3 ( 2 )= 2 fib3 ( 3 )= 3 fib3 ( 4 )= 5 fib3 ( 5 )= 8 fib3 ( 6 )= 13 fib3 ( 7 )= 21 fib3 ( 8 )= 34 fib3 ( 9 )= 55 fib3 ( 10 )= 89 fib3 ( 11 )= 144 fib3 ( 12 )= 233 fib3 ( 13 )= 377 fib3 ( 14 )= 610 fib3 ( 15 )= 987 fib3 ( 16 )= 1597 fib3 ( 17 )= 2584 fib3 ( 18 )= 4181 fib3 ( 19 )= 6765 fib3 ( 20 )= 10946 fib3 ( 21 )= 17711 fib3 ( 22 )= 28657 fib3 ( 23 )= 46368 fib3 ( 24 )= 75025 elapsed time = 0.0166666666046 """