[Tutor] fibonacci

Gregor Lingl glingl@aon.at
Fri Feb 14 07:24:02 2003


Jayprasad J. Hegde schrieb:

>On Wed, Feb 12, 2003 at 07:51:33PM +1100, Alfred Milgrom wrote:
>[ snip ] 
>  
>
>>Just as an exercise, I was unable to create a one-line recursive fibonacci 
>>generator, but the following works correctly for all values of n greater 
>>than 2.
>>
>>def fib(n):
>>    return (n<5)*(n-2) or fib(n-1) + fib(n-2)
>>    
>>
>
>I would not recommend creating a second order (containing two recursive elements e.g. "fib (n - 1)" and  "fib (n - 2)" ) recursive function like this. 
>It would be best if you can find...
>1. a recursive function with a single recursive element, or
>2. sticking to an iterative variant. 
>  
>

Ok. Somtimes one has a lot of work to do and nevertheless wastes time
for some questionable - if not useless - task. So I arrived at this:

def fib1liner(n, f=[0,1]):
    return(n+1>len(f))and[(lambda x:f.append(f[-2]+f[-1]))(i)for i in 
range(n+1-len(f))]and 0 or f[n]

I would not have posted it here if it had not a remarkable property ;-)
it is about a factor 50 faster than the (also iterative) classic from the
tutorial (as already  posted in this thread) :

def fib(n):
    a,b=0,1
    for i in range(n):
        a,b=b,a+b
    return a

from the turorial.

This can be seen  using:

from time import clock

def test(afib, n = 500):
    a = clock()
    for i in range(n):
        x = afib(i)
    b = clock()
    print b-a
    print x

to measure the time for calculating the first 1000 fibonacci numbers
(I use Python 2.2, which converts automtically to longints if needed):

 >>> test(fib)
3.64362016859
26863810024485359386146727202142923967616609318986952340123175997617981700247881689338369654483356564191827856161443356312976673642210350324634850410377680367334151172899169723197082763985615764450078474174626
 >>> test(fib1liner)
0.0725899317958
26863810024485359386146727202142923967616609318986952340123175997617981700247881689338369654483356564191827856161443356312976673642210350324634850410377680367334151172899169723197082763985615764450078474174626

Isn't this nice? (If you don't have to care about use of memory on your 
machine  ;-) )

Gregor

P.S.: ... and look, with time fib1liner becomes even faster:

 >>> test(fib1liner)
0.0172815211761
26863810024485359386146727202142923967616609318986952340123175997617981700247881689338369654483356564191827856161443356312976673642210350324634850410377680367334151172899169723197082763985615764450078474174626
 >>>