tags:

views:

350

answers:

9

code 1:

public static int fibonacci (int n){ 
        if (n == 0 || n == 1) { 
        return 1; 
        } else { 
        return fibonacci (n-1) + fibonacci (n-2); 
        } 

    } 

how can you use fibonacci if you haven't gotten done explaining what it is yet? I've been able to understand using recursion in other cases like this:

code two:

class two 
{
 public static void two (int n) 
 {
  if (n>0) 
  {
  System.out.println (n) ;
  two (n-1) ;
  }
  else
  {
   return ;
  }
 } 

 public static void main (String[] arg) 
 {
  two (12) ;
 }
}

In the case of code 2 though n will eventualy reach a point at which it doesnt satisfy n>0 and the method will stop calling itself recursivly. in the case of code 2 though i don't see how it would be able to get itself from 1 if n=1 was the starting point to 2 and 3 and 5 and so on. Also i don't see how the line `return fibonacci (n-1) + fibonacci (n-2) would work since fibbonacci n-2 has to contain in some sense fibonacci n-1 in order to wrok but it isn't there yet.

I know my question is worded poorly but looking at this is making my mind explode. the book i'm looking at says it will work.

how does it work? `

+1  A: 

Try to draw an illustration yourself, you will eventually see how it works. Just be clear that when a function call is made, it will fetch its return value first. Simple.

N 1.1
+1  A: 

Try debugging and use watches to know the state of the variable

Sri Kumar
what does that mean?
David
Sri Kumar means using the debugger on your IDE and watching certain variables as they change value through execution of the function.Most IDEs can do this fairly easily.
chustar
Thanks Chustar!
Sri Kumar
the only IDE i have on my computer is eclypse and when i opened it it looked intimidatingly complex. is there a simpler one that will do this that i can use?
David
write the code in your head and compile it in your eyes
drorhan
+8  A: 

Well, putting aside what a compiler actually does to your code (it's horrible, yet beautiful) and what how a CPU actually interprets your code (likewise), there's a fairly simple solution.

Consider these text instructions:

To sort numbered blocks:

  1. pick a random block.
  2. if it is the only block, stop.
  3. move the blocks with lower numbers to the left side, higher numbers to the right.
  4. sort the lower-numbered blocks.
  5. sort the higher-numbered blocks.

When you get to instructions 4 and 5, you are being asked to start the whole process over again. However, this isn't a problem, because you still know how to start the process, and when it all works out in the end, you've got a bunch of sorted blocks. You could cover the instructions with slips of paper and they wouldn't be any harder to follow.

Ryan Prior
so are 4 and 5 really just blocksort () within blocksort?
David
that is correct - steps 4 and 5 are the recursive calls.
Ryan Prior
if this were an actualy program wouldn't 4 and 5 be the same single command/line?
David
+1: I love this explanation of recursion. So simple my toddler could do it, eh <grin>.
Software Monkey
+1  A: 

The trick is that the first call to fibonacci() doesn't return until its calls to fibonacci() have returned.

You end up with call after call to fibonacci() on the stack, none of which return, until you get to the base case of n == 0 || n == 1. At this point the (potentially huge) stack of fibonacci() calls starts to unwind back towards the first call.

Once you get your mind around it, it's kind of beautiful, until your stack overflows.

Spike
+1 for Stack Overflow reference, I think.
chustar
+2  A: 

"How can you use Fibonacci if you haven't gotten done explaining what it is yet?"

This is an interesting way to question recursion. Here's part of an answer: While you're defining Fibonacci, it hasn't been defined yet, but it has been declared. The compiler knows that there is a thing called Fibonacci, and that it will be a function of type int -> int and that it will be defined whenever the program runs.

In fact, this is how all identifiers in C programs work, not just recursive ones. The compiler determines what things have been declared, and then goes through the program pointing uses of those things to where the things actually are (gross oversimplification).

Jesse Millikan
+1  A: 

Understanding recursion requires also knowing how the call stack works i.e. how functions call each other.
If the function didn't have the condition to stop if n==0 or n==1, then the function would call itself recursively forever. It works because eventually, the function is going to petter out and return 1. at that point, the return fibonacci (n-1) + fibonacci (n-2) will also return with a value, and the call stack gets cleaned up really quickly.

chustar
+3  A: 
Alexander Malakhov
ermm... it turns out, that post auto transfers to wiki after 8 edits :)
Alexander Malakhov
+1  A: 

Let me walkthrough the execution considering n=3. Hope it helps.

When n=3 => if condition fails and else executes

return fibonacci (2) + fibonacci (1);  

Split the statement:

  1. Find the value of fibonacci(2)
  2. Find the value of fibonacci(1)
    // Note that it is not fib(n-2) and it is not going to require fib(n-1) for its execution. It is independent. This applies to step 1 also.
  3. Add both values
  4. return the summed up value

The way it gets executed(Expanding the above four steps):

  1. Find the value of fibonacci(2)

    1. if fails, else executes
    2. fibonacci(1)
      1. if executes
      2. value '1' is returned to step 1.2. and the control goes to step 1.3.
    3. fibonacci(0)
      1. if executes
      2. value '1' is returned to step 1.3. and the control goes to step 1.4.
    4. Add both
      1. sum=1+1=2 //from steps 1.2.2. and 1.3.2.
    5. return sum // value '2' is returned to step 1. and the control goes to step 2
  2. Find the value of fibonacci(1)

    1. if executes
    2. value '1' is returned
  3. Add both values

    1. sum=2+1 //from steps 1.5. and 2.2.
  4. return the summed up value //sum=3
Veer
A: 

I'll explain what your PC is doing when executing that piece of code with an example:

Imagine you're standing in a very big room. In the room next to this room you have massive amounts of paper, pens and tables. Now we're going to calculate fibonacci(3):

We take a table and put it somewhere in the room. On the table we place a paper and we write "n=3" on it. We then ask ourselves "hmm, is 3 equal to 0 or 1?". The answer is no, so we will do "return fibonacci (n-1) + fibonacci (n-2);".

There's a problem however, we have no idea what "fibonacci (n-1)" and "fibonacci (n-2)" actually do. Hence, we take two more tables and place them to the left and right of our original table with a paper on both of them, saying "n=2" and "n=1".

We start with the left table, and wonder "is 2 equal to 0 or 1?". Of course, the answer is no, so we will once again place two tables next to this table, with "n=1" and "n=0" on them.

Still following? This is what the room looks like:

n=1

n=2 n=3 n=1

n=0

We start with the table with "n=1", and hey, 1 is equal to 1, so we can actually return something useful! We write "1" on another paper and go back to the table with "n=2" on it. We place the paper on the table and go to the other table, because we still don't know what we're going to do with that other table.

"n=0" of course returns 1 as well, so we write that on a paper, go back to the n=2 table and put the paper there. At this point, there are two papers on this table with the return values of the tables with "n=1" and "n=0" on them, so we can compute that the result of this method call is actually 2, so we write it on a paper and put it on the table with "n=3" on it.

We then go to the table with "n=1" on it all the way to the right, and we can immediately write 1 on a paper and put it back on the table with "n=3" on it. After that, we finally have enough information to say that fibonacci(3) returns 3.


It's important to know that the code you are writing is nothing more than a recipe. All the compiler does is transform that recipe in another recipe your PC can understand. If the code is completely bogus, like this:

    public static int NotUseful()
    {
        return NotUseful();
    }

will simply loop endlessly, or as in my example, you'll keep on placing more and more tables without actually getting anywhere useful. Your compiler doesn't care what fibonacci(n-1) or fibonacci(n-2) actually do.

Alex ten Brink