Why is this blowing the stack, thought it was tail-recursive...

Terry Reedy tjreedy at udel.edu
Sun Jul 13 01:25:18 CEST 2008



ssecorp wrote:
> def fib(n):
>     def fibt(a, b, n):
>         if n <= 1:
>             return b
>         else:
>             return fibt(b, a + b, n - 1)
>     if n == 0:
>         return 0
>     else:
>         return fibt(0, 1, n);
> 
> and can memoization speed up this even more? tesintg with memoization
> doesnt really say anything because it is so fast it is instant anyway.

Except for the fact that a+b gets slower as a and b get bigger, this 
would already be linear time in n.  Memoization (here by means of a 
linear list) only helps if the list is preserved and one makes repeated 
requests for various fib values.

I am just curious what input you tried that blew the stack?  It had to 
be pretty large.

The stack problem, by the way, is one reason linear induction is usually 
written in Python with iteration syntax instead of recursion syntax. 
Another is the extra simplicity.

def fib(n):
   a,b = 1,0
   while n:
     a,b,n = b, a+b, n-1
   return b

A third is the ease of conversion to a (space-efficient) generator function.

def fib_gen()
     a,b = 1,0
     while True:
         yield b
         a,b = b, a+b

The generator it produces can be used, for instance, to fill a list 
(linear memo) 'on demand'.

A model that leads to the linear algorithm (as opposed to the double 
recursion derived from Fibonacci's rabbit model) is as follows:
A population consists of juveniles and adults.  In one period, juveniles 
become adults (which never die) and adults birth (or bud off) one 
juvenile.  (Yeast are somewhat like this.)  At time 0, we start with 1 
juvenile and 0 adults.  How many adults are there at time n?

Terry Jan Reedy




More information about the Python-list mailing list