0

I'am getting my head around recursion from the very basics, since I struggled in the past. I'm looking at this Factorial solution:

int Factorial(int n)
{
    if (n == 0)
    {
        return 1;
    }
    return n * Factorial(n - 1);
}

So the function keeps calling itself until n == 0. Then it goes on returning values at each call. Now that's what I don't understand: When it comes back from base condition it returns a value and it keeps adding values from each of the calls.

Where are these values being stored to finally be able to return the total sum?

Chris Yates
  • 91
  • 1
  • 6
  • 6
    they are stored on the stack. If your stack is too small, you will get a stack overflow. – wimh Sep 27 '15 at 09:46
  • Possible duplicate of [this](http://stackoverflow.com/a/32794819/2686112) question! Suggest you to read my answer! Talks about the intricacies of Recursion! – Rahul Jha Sep 27 '15 at 10:39

3 Answers3

3

As you correctly interpret, the function Factorial calls itself unless the argument is 0. Since it calls itself with n - 1, eventually the sequence of recursive calls will stop after n steps. Each call is a new instance or invocation of the function, the computation is suspended until the new instance returns. The state of a given instance is kept in memory in an area called the stack (on most current environments).

When the final instance called with the value 0 returns, the last calling instance can finish its computation and return 1 * 1 to its caller, and so on until the initial instance can finish its multiplication and return the factorial of its argument.

------- stop reading here unless you are interested in implementation details --------

First problem with the above code, if n is negative or very large, the program will likely invoke undefined behaviour because of too many recursive calls, each consuming some stack space, a limited resource.

Second problem: the int type has a limited range of possible values. On most curent systems, int is stored as 32 bits. Factorials grow very quickly, so Factorial(12) yields 479001600, which causes arithmetic overflow when multiplied by 13 because the result 6227020800 cannot fit in 32 bits. Arithmetic overflow invokes undefined behaviour.

You can try and compile your Factorial function on this site: http://gcc.godbolt.org/# . It has an interactive compiler and shows the assembly code. Try different optimizer options:

  • -m32 -O1 will give a recursive version, not too difficult to understand
  • -m32 -O2 shows that the compiler is astute enough to transform your recursive C implementation to an iterative assembly version, both shorter and faster than the -O1 version.
  • -m32 -O3 yields vastly more complex code, involving SIMD instructions on MMX registers... potentially faster than the -O2 version, but completely over-engineered since a simple small lookup table without a single test would suffice:

    int Factorial(int n) {
        static int f32[16] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320,
                               362880, 3628800, 39916800, 479001600,
                               0, 0, 0 };
        return f32[n & 15];
    }
    

Notice how one can take advantage of undefined behaviour semantics (anything goes) to simplify the implementation and remove tests. Compilers are allowed to do that and some of them do indeed.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Ok thanks for the explanation. But still dont know where return values stays, f(2) = 2* f(1), f(1) = 1 * f(0). Ok now f(0) returns 1, it will simply replace f(0) above with 1? – Chris Yates Sep 27 '15 at 10:01
  • 1
    On most CPUs, the function return value is returned in a fixed CPU register and control is transferred back to the calling code. In your example, the calling instance will then multiply this register with the value of its argument, stored on the stack, store the result in the same register, unwind its own stack space and transfer control back to its caller. – chqrlie Sep 27 '15 at 10:16
  • @ChrisYates - I think that you don't understand what "the stack" is in a computer. [Please look at this page for an explanation](http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/stack.html). – Bob Jarvis - Слава Україні Sep 27 '15 at 10:55
  • @chqrlie plus one! :) Now, let's clean up the unnecessary comments :) – Ziezi Sep 27 '15 at 11:43
0

To recursively compute its result on a given input, a recursive function calls (a copy of) itself with a different ("smaller" in some way) input and uses the result of this call to construct its result. The recursive call does the same, unless the base case has been reached. Thus a call stack develops in the process. For example, to compute Factorial(3), this recursively calls in turn Factorial(2), Factorial(1), Factorial(0) ("winding up" the stack), at which point recursion terminates with Factorial(0) = 1, and then the stack unwinds in reverse order and the results are calculated on the way back along the call stack to the initial call frame Factorial(3), where the final result is calculated as 3*2 =: 6 and finally returned. In this example a function returns a single value.

Nitin Tripathi
  • 1,224
  • 7
  • 17
  • They are different copies which means that declaring variables is problematic since they will be different in each of the calls right? – Chris Yates Sep 27 '15 at 10:04
  • If you define a variable in recursive function, then scope of the variable will be with in function. so yes, value of variable won't persists, unless variable is defined as static. – Nitin Tripathi Sep 27 '15 at 10:08
0

Quick answer:

Everything is stored on the stack in the respective activation record1.

Here is a depiction of the function calls (on the left) and of the stack (on the right), of the recursive function implementing factorial: enter image description here

Your function int Factorial(int n); is using recursion. The first return is called base case and it acts as a termination condition and the second return is the recursive step, which results in a call to the same function with one of the parameters (used in the base case if condition statement) modified. The result is accumulated and returned after the base condition is reached.

Here is an excellent explanation of recursion, using exactly factorial as an example.


1. On computer architecture level the result is stored in a specific register, accumulating the final result.

Community
  • 1
  • 1
Ziezi
  • 6,375
  • 3
  • 39
  • 49