Reputation: 77
I wrote a simple recursive fibonacci function:
def recursive_fibonacci(n):
if n == 0:
return 0
if n == 1:
return 1
if n > 1:
return recursive_fibonacci(n-1) + recursive_fibonacci(n-2)
and tried to run a large value in it:
print(recursive_fibonacci(100))
Nothing came out of the console and the fan on my mac started spinning violently
Can someone explain what is going on. What is happening internally in the stack frame?
Upvotes: 0
Views: 916
Reputation: 78546
Building on Prune's nice answer you can easily memoize the function calls so that each value of n
is only computed once by passing a mutable argument (a dict) in the function definition and storing already computed values in the dict:
def recursive_fibonacci(n, mem={}):
if n == 0 or n == 1:
return n
else:
if n-1 not in mem:
mem[n-1] = recursive_fibonacci(n-1)
if n-2 not in mem:
mem[n-2] = recursive_fibonacci(n-2)
return mem[n-1] + mem[n-2]
print(recursive_fibonacci(100))
# 354224848179261915075
Already computed values are looked up the dict and would not require further recursive calls.
Upvotes: 2
Reputation: 77837
A call to your routine with argument N
makes on the order of phi^N
total calls. For N=100, this is on the order of 10^20 calls. Don't wait for the output at N=100; you won't live that long.
However, you can memoize the function. Look up the term; there's also a Python package to do that for you automatically. The idea is to store the result of each value call; for any N
, you compute f(N)
only once; thereafter, you just look up the value in a table.
Upvotes: 3
Reputation: 615
The primitive recursive solution takes a lot of time. The reason for this is that for each number calculated, it needs to calculate all the previous numbers more than once. Take a look at the following image.
Tree representing fibonacci calculation
It represents calculating Fibonacci(5) with your function. As you can see, it computes the value of Fibonacci(2) three times, and the value of Fibonacci(1) five times. That just gets worse and worse the higher the number you want to compute.
What makes it even worse is that with each fibonacci number you calculate in your list, you don't use the previous numbers you have knowledge of to speed up the computation – you compute each number "from scratch." The easiest way is to just create a list of fibonacci numbers up to the number you want. If you do that, you build "from the bottom up" or so to speak, and you can reuse previous numbers to create the next one. If you have a list of the fibonacci numbers [0, 1, 1, 2, 3], you can use the last two numbers in that list to create the next number and return the last number of the listwhich is your final answer.
def fib_to(n):
fibs = [0, 1]
for i in range(2, n+1):
fibs.append(fibs[-1] + fibs[-2])
return fibs[-1]
Upvotes: 1