4

I am trying to understand the recursion call in the below code snippet.

static long fib(int n) {
    return n <= 1 ? n : fib(n-1) + fib(n-2);
}

Which function call does get called first? How does the equation work after the calls?

Do both of these get called once and then equation applied or first one called and then the 2nd one?

Maybe a very simple question!

Kevin Rave
  • 13,876
  • 35
  • 109
  • 173
  • 2
    you can try to print the value of n, and find out by yourself. – David Bejar Oct 16 '12 at 17:13
  • 2
    @DavidBejar "Try it and see" isn't always good advice, particularly in cases where the behavior could be implementation-defined or undefined (`i = i++`). – John Kugelman Oct 16 '12 at 17:15
  • 5
    It doesn't help if all you want to know is the order in which the functions are called, but Structure and Interpretation of Computer Programs, a very popular textbook, has a great visualization of this algorithm in [Section 1.2.2](http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.2). – Dan Monego Oct 16 '12 at 17:25
  • @JohnKugelman "Try it and see" is especially dangerous advice when dealing with recursion, where the function may never return if you get it wrong ;) – itsbruce Oct 17 '12 at 15:39

5 Answers5

3

Java and C&sharp;

Sub-expressions are evaluated in left-to-right order. fib(n-1) is evaluated before fib(n-2). See What are the rules for evaluation order in Java?

It's important to note that the order of evaluation doesn't matter here since fib() does not have any side effects.

C and C++

The two functions are called in an indeterminate order, and once both have been called their return values are added together and returned. The left function could be called first, or the right one first, you don't know.

That may seem problematic, but it's not, because the order they're called doesn't matter. Calling fib(i) does not have any side effects (e.g. modifying other variables, printing a message, etc.), so the two function calls are entirely independent.

One compiler might decide to evaluate the left side before the right:

 1. f(3)
 2.   f(2)
 3.     f(1)
 4.       return 1
 5.     f(0)
 6.       return 0
 7.     return 1 + 0
 8.   f(1)
 9.     return 1
10.  return 1 + 1

Another one might decide to evaluate the right side before the left:

 1. f(3)
 2.   f(1)
 3.     return 1
 4.   f(2)
 5.     f(0)
 6.       return 0
 7.     f(1)
 8.       return 1
 9.     return 1 + 0
10.  return 1 + 1
Community
  • 1
  • 1
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • Hmmm.. If that is the case ` indeterminate order`, how do we predict the answer? – Kevin Rave Oct 16 '12 at 17:17
  • I guess, if its totally independent, then we would not get desired answer. Lets say, n is 10, then we expect the equation to be 9 + 8. If first one gets called first, the result 9, and lets say the first one again gets called, the n is 8 and then the 2nd one is called, the result is 8, so we get 8+8, which is not what we want. maybe I did not understand your answer correctly? – Kevin Rave Oct 16 '12 at 17:21
  • You're not getting it, Kevin. It doesn't matter in which order the **fib(n-1)** and **fib(n-2)** are made because a) both have to be evaluated before the expression `fib(n-1) + fib(n-2)` can be evaluated and b) the two calls are completely separate and independent and do not depend on each other for their results. **fib(n-1)** will always and reliably return one value for any one value of n, **fib(n-2)** will always return another specific value and adding those two values together will always give the same result for any one value of n. – itsbruce Oct 17 '12 at 09:44
  • Kevin, just assume for a moment that **fib** is a reliable function that works and always returns the right value for **fib(n)**. So **fib(6)** returns 5 (which is the 6th element in the series) and **fib(7)** returns 8 (which is the 7th). Now, suppose you call **fib(8)**. The **fib** function tries to calculate it by adding **fib(6)** and **fib(7)**. How can it matter whether it calculates **fib(6)** first or second? It still adds the answer to 8 to get 13. – itsbruce Oct 17 '12 at 09:58
3

The order of evaluation for the + operator might not be defined (it's implementation-dependent) meaning: either fib(n-1) or fib(n-2) could be executed first. Either way the result will be the same, in this particular case it doesn't matter: both recursive calls will be computed and added together before being returned, from the calling place you'll only see the end result of the sum.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
1

It doesn't matter which function is called first. This function returns the nth number in the Fibonacci sequence, which can always be found by adding the previous two numbers together (with the special case that the first two in the sequence are 0 and 1).

So what this function does to work out fib(n) is to ask for fib(n-1) and fib*(n-2) and add them together to get fib(n). Of course, fib(n-1) works by asking for fib(n-2) and fib(n-3), while fib(n-2) works by asking for fib(n-3) and fib(n-4) and so on until the very beginning of the sequence (0 and 1) is reached. Since those can be returned without any further recursion, the recursion ends and each open function returns to the one that called it, all the way back up the chain.

There's a more efficient way to do this which doesn't require two separate recursions, but it wouldn't look so elegant.

itsbruce
  • 4,825
  • 26
  • 35
0

Gcc -S fib.c:

    subl    $1, %eax
    movl    %eax, (%esp)
    call    _fib
    movl    %eax, %ebx
    movl    8(%ebp), %eax
    subl    $2, %eax
    movl    %eax, (%esp)
    call    _fib

So, the left one is called first. What then? Well, it call fib also for (n-2) without knowing that the right branch is also calculating the same thing.

This well known example has a complexity of O(n^2), meaning that if n=10, it calls it self with different parameters ~100 times, even though 10 times is more than enough.

Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57
0

To understand this i used below code and the output cleared all the doubt:(C#)

        static void Main(string[] args)
    {
        var data = series(5);
        Console.WriteLine(data);
    }

    public static int series(int n)
    {
        Console.WriteLine(n);
        if (n ==2)
        {
            return 1;
        }
        if (n == 50)
        {
            return 3;
        }
        else
        {
            return series(2) + series(50);
        }
    }

Output: 5 2 50 4

In short it will complete the recursion of left expression then move to right.

MVijayvargia
  • 331
  • 2
  • 10