If I put return (n-1)*n that is 8-1=7*8=56
But if I put like in the book example return factorial(n-1)*n then it returns 40320.
How does the calculation/math works? It returns a function, it return itself - right?
But I don't know how this works. How does it get to the number 40320?
const factorial = function(n) {
if (n === 0) {
return 1
} else {
return factorial(n - 1) * n
}
}
console.log(factorial(8))
We can calculate the factorial of any natural number (n) by doing:
n! = n * n-1 * n-2 * n-3 * ... * 1
Eg:
4! = 4 * 3 * 2 * 1 = 24
This can be simplified to:
n! = n * (n-1)!
Eg:
4! = 4 * (4-1)! = 4 * 3!
3! = 3 * (3-1)! = 3 * 2!
2! = 2 * (2-1)! = 2 * 1!
1! = 1 * (1-1)! = 1 * 0!
0! = 1
So solving this, we can now work back up our equations:
0! = 1
1! = 1 * 0! = 1 * (1) = 1 // <--- subbing in as we now know the result of 0! to be 1
2! = 2 * 1! = 2 * (1) = 2
3! = 3 * 2! = 3 * (2) = 6
4! = 4 * 3! = 4 * (6) = 24
When we do this with code, we can use recursion. This means we call a function within itself. Taking the above example we can do this using a function called fact() instead of using the ! notation:
fact(4) = 4 * fact(4-1) = 4 * fact(3) // same as: 4! = 4 * (4-1)! = 4 * 3!
So after running fact(4), we see that we are returning / trying to calculate the result of 4 * fact(3). But we don't know what fact(3) is yet, so we need to calculate it:
fact(3) = 3 * fact(3-1) = 3 * fact(2)
Here we are trying to calculate 3 * fact(2), but we don't know what fact(2) is yet, so we need to work it out:
fact(2) = 2 * fact(2-1) = 2 * fact(1)
Again, we need to work out what fact(1) is:
fact(1) = 1 * fact(1-1) = 1 * fact(0)
Lastly, we need to work out what fact(0) is:
fact(0) = 1
Here we get fact(0) is equal to 1. Notice how fact(0) returns a value which doesn't have a reference to another fact call. This means that we have reached our base case (defined in your if(n===0)) and can now calculate/traverse our previous equations we didn't know how to answer.
So going back up to fact(1) we now replace the call to fact(0) with 1
fact(1) = 1 * fact(0) 1 = 1
Now we know what fact(1) is, we can now calculate fact(2):
fact(2) = 2 * fact(1) 1 = 2
Now we know what fact(2) is, we can calculate fact(3):
fact(3) = 3 * fact(2) 2 = 6
Lastly, we can calculate fact(4):
fact(4) = 4 * fact(3) 6 = 24
So, using this, we get fact(4) = 24
This is the basis of how this recursive function works.
So if you use return (n-1)*n at the end of your function instead of return fact(n-1) * n you are simply just doing one return, and not calling your function again to calculate the factorial of n-1.
It returns factorial(n-1)*n instead of (n-1)*n, hence the calculation would not be just 8*7 = 56. Instead, since it is returning a call to itself, the final calculation would be 8*7*6*5*4*3*2*1 = 40320.
This is called a recursive function. When you called factorial(8), it will return factorial(7)*8, which called factorial(7) before returning. factorial(7) returns factorial(6)*7, which called factorial(6) before returning. This goes all the way until factorial(2) returns factorial(1)*1, which called factorial(1) that returns 1.
Then factorial(2) returns factorial(1)*2 = 1*2 = 2, factorial(3) returns factorial(2)*3 = 2*3 = 6, factorial(4) returns factorial(3)*4 = 6*24 = 24, and so on. Lastly, factorial(8) returns factorial(7)*8 = 5040*8 = 40320
Related
Gif for the debugger in console
So, when running this, i'm a bit confused how fac parameter is maintaing the state. what i understand by factorial(4) is
4 * (4-1) // 4 * 3 = 12
12 * (3-1) // 12 * 2 = 24
24 * (2-1) // 24 * 1 = 24
function factorial(fac){
debugger
if(fac == 1)
return fac
return fac * factorial(fac-1)
}
factorial(4)
Every call to factorial has its own fac parameter, with its own value. So when, in the first call (during factorial(4)), when you do:
return fac * factorial(fac - 1);
that calls factorial again, passing in the value resulting from fac - 1 (3). That new call receives fac = 3 and does its work with it. While that's happening, the first call is waiting to get the return value from it (let's call it retVal) so it can finish the return fac * ____________ by plugging retVal in where ____________ is.
Eventually, a call to factorial does its work by returning fac instead of calling factorial again, which means the one that called it can complete its work and return its return value, which means the one that called it can do that, until we get back to the top one that returns the overall result.
Here's an attempt to show how the calls stack up (using indentation for showing the recursive calls):
factorial(fac = 4)
factorial(fac = 3)
factorial(fac = 2)
factorial(fac = 1)
return 1
|
v
return 2 * 1 = 2
|
+−−−−−−−+
|
v
return 3 * 2 = 6
|
+−−−−−−−+
|
v
return 4 * 6 = 24
Note that when factorial(1) is running, there are four different fac parameters in memory, fac = 4 (the outermost call), fac = 3 (the first recursive call), fac = 2 (the next recursive call), and fac = 1 (the last recursive call before the returns kick in).
Think of the function calls as stack, so when fac(4) is called this stack is formed
factorial(1)
^
Calls^
^
factorial(2)
^
Calls^
^
factorial(3)
^
Calls^
^
factorial(4)
then this stack is resolved from top down. so value of fac is being changed at every call
factorial(1) ==> fac = 1, return value =1
then resolves
factorial(2) ==> fac = 2, return value =2*factorial(1) > already in memory
then resolves
factorial(3) ==> fac = 3, return value =3*factorial(2) -> in memory
then resolves
factorial(4) ==> fac = 4, return value =4*factorial(3) -> in memory
You can simplify pure expressions the same way you can simplify mathematical expressions.
factorial(4)
= 4 * factorial(4 - 1) // because 4 != 1
= 4 * factorial(3)
= 4 * (3 * factorial(3 - 1)) // because 3 != 1
= 4 * (3 * factorial(2))
= 4 * (3 * (2 * factorial(2 - 1))) // because 2 != 1
= 4 * (3 * (2 * factorial(1)))
= 4 * (3 * (2 * 1)) // because 1 == 1
= 4 * (3 * 2)
= 4 * 6
= 24
This is a very powerful way of reasoning about expressions. It's one of the advantages of writing pure code instead of impure code. You can't simplify impure expressions in this manner because impure code has side effects which need to be tracked.
Anyway, why don't you try to simplify the following result expression by yourself? It'll help you understand how recursion works in functional programs. No need to think about function call stacks or anything else technical. Just get a pen and paper and start simplifying the expression like you would do in your 5th grade math class.
function fib(n) {
if (n === 0) return 1;
if (n === 1) return 1;
return fib(n - 1) + fib(n - 2);
}
const result = fib(5);
console.log(result); // 8
A few tips to remember.
When replacing a function call with its result, wrap it in parentheses.
Always simplify the leftmost expression first. This mimics the way JavaScript works.
Simplify expressions one at a time. Don't simplify multiple expressions in a single step.
I'm learning to work with recursion and so far it went well with basic examples. However I want to calculate the factorial, but I don't understand what happened step-by-step. If I do it imperatively I understand it but I fail on this example:
return x * fac(x-1); gives me back 5 * 4, so far soo good, but what happens now? Does it mean it become 20 now? So my next iteration would be then 20 * 19?
const fac = (x) => {
if(x <= 1) {
return x;
}
return x * fac(x-1);
};
console.log(fac(5)); // 120
just walk through the logic.
1. fac(5) yields 5 * fac(4)
2. fac(4) yields 4 * fac(3)
3. fac(3) yields 3 * fac(2)
4. fac(2) yields 2 * fac(1)
5. fac(1) yields 1
substituting from bottom to top, you get
fac(5) = 5 * 4 * 3 * 2 * 1
I think i understand that part now and the difference between 4 and fac(4). The steps look like:
5. 5 * // ()
4. 4 * // (20)
3. 3 * // (60)
2. 2 * // (120)
1. 1 * // (120)
However, I have another example which i cant resolve step by step, while i can see the logic in the imperatively programming.
let fibo = (x) => {
if(x<=2) {return 1;}
return fibo(x-1) + fibo(x-2);
};
console.log(fibo(4)); //3
I cant resolve step by step what return fibo(x-1) + fibo(x-2); values this gives me each step. On the imperatively programming it is
function fibonacci(num){
var a = 1, b = 0, temp;
while (num >= 1){
temp = a;
a = a + b;
b = temp;
num--;
}
return b;
}
console.log(fibonacci(4); // 3
where the steps would be like
4. b = 1
3. b = 1
2. b = 2
1. b = 3
Please, someone, tell me how is the result 384 here.
According to me:
Called function value is greater than 2 so, the result should be
8 * fac(8 - 2)
64-2
ans: 62
I understand something happening with "fac" please explain.
let factoria = function fac(n){
return n < 2 ? 1 : n * fac(n - 2);
}
console.log(factoria(8));
// result 384
This line n * fac(n - 2) is recursively calling the itself with new value. At first it will be called with 8 * fac(8 - 2)so now fac will be called again with 6, then again with 4 and so on
let factoria = function fac(n) {
console.log(n)
return n < 2 ? 1 : n * fac(n - 2); // recursive function
}
console.log(factoria(8));
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Can someone explain how this recursive function produces 5 * 4 * 3 * 2 * 1 to get 120?
var factorial = function(n){
if (n === 0)
return 1;
else
return n * factorial(n - 1);
};
factorial(5); // spits out 120
If we use 5 like like in the example, once we got to the else statement wouldn't
return n * factorial(n - 1);
translate to 'return 5 multiplied by the factorial function(5-1); 5 times...
Am I wrong to feel this recursive function feels like a 'for loop?'
No, recursion and loops have a lot in common. In particular, it's very important that they both have a termination condition. :-) In this case, that termination condition is n === 0.
The best way to understand this is to single-step through the code in a debugger. Your browser has one, so you could put that code in a page and load it and walk through it.
To get you started:
You call factorial(5). Since n is not === 0, factorial calls itself with n - 1 (4)
Now we've recursed one level, and we're running factorial(4) (the call to factorial(5) still hasn't returned, it's waiting on us). Since n is not === 0, we call factorial(3) and wait for it to return.
...rinse, repeat until factorial(0) is called. Since n === 0 is true (at that point, there are five calls to factorial outstanding and stacked up), factorial(0) returns 1, and we can start unwinding the stacked up calls.
Now factorial(1) can finish by multiplying the result it got from factorial(0) by its copy of n (1) and returning that.
...which lets factorial(2) finish and multiply that by 2...
...rinse repeat...
Or to put it another way showing the nesting (recursion):
factorial(5)
return 5 * factorial(4)
return 4 * factorial(3)
return 3 * factorial(2)
return 2 * factorial(1)
return 1 * factorial(0)
return 1
And because you can't get enough diagrams (or at least I can't):
factorial(5) factorial(4) factorial(3) factorial(2) factorial(1) factorial(0)
calls ---------->
calls ---------->
calls ---------->
calls ---------->
calls ----------->
n is 0, so
returns 1
|
returns 1 * 1<-----------+
= 1
|
returns 2 * 1<------------+
= 2
|
returns 3 * 2<------------+
= 6
|
returns 4 * 6<------------+
= 24
|
returns 5 * 24<-----------+
= 120
Result: 120
Side note: That function doesn't allow for negative numbers; it could probably use a guard at the beginning...
The n changes:
5 * factorial(5-1) = 5 * 4 * factorial(4-1) = 5 * 4 * 3 * factorial(3-1) = 5 * 4 * 3 * 2 * factorial(1-1) = 5 * 4 * 3 * 2 * 1
Also to make this function better you could stop it when n is equal to 1, since the factorial of 1 is 1:
var factorial = function(n){
if (n === 1 || n === 0)
return 1;
else
return n * factorial(n - 1);
};
This function says: if you want to calculate factorial(5), well, that's really just
5 * factorial(4)
and if you want to calculate factorial(4), that's really just 4 * factorial(3)
5 * 4 * factorial(3)
and the thing about factorial(3) is that it's really just 3 * factorial(2)
5 * 4 * 3 * factorial(2)
and so on. But when you get down to factorial(0), the function finally stops (because of the if n == 0 case) and returns 1, without any further recursion. So you get
5 * 4 * 3 * 2 * 1
return n * factorial(n - 1) translates to (on the first run), "return (5 * 4!)". It doesn't do anything 5 times.
If we use 5 like like in the example, once we got to the else statement wouldn't
return n * factorial(n - 1);
translate to 'return 5 multiplied by the factorial function(5-1); 5 times...
No, it would translate to 'return n multiplied by the factorial function (n-1)' (5 times, because n starts at 5, decrements and enters the else clause until it reaches 0).
When you first enter the function, n is equal to 5.
The if clause checks if n is equal to 0. It isn't, so it goes to:
The else clause. Which translates to 'return 5 multiplied by the factorial function (which you're in) (5 - 1).
When you enter the factorial function, n is now 4.
Repeat all of those steps until n is equal to 0. The if clause will then be true and the function will return 1.
So 1 is returned from factorial(0). Factorial(1) returns 1 * factorial(0), so 1 * 1 = 1.
Factorial(2) returns 2 * factorial(1), so 2 * 1 = 2.
Factorial(3) returns 3 * factorial(2), so 3 * 2 = 6.
Factorial(4) returns 4 * factorial(3), so 4 * 6 = 24.
Factorial(5) returns 5 * factorial(4), so 5 * 24 = 120.
I'm learning JavaScript, and one of the exercises was to write a power function. I should also learn math because this will surely sound stupid.
I know intuitively that $2 ^ 4 = 16$ since $2 * 2 * 2 * 2 = 16$. But reading through the function, it appears that it should return 12, not 16.
If we plug the numbers in, it should look like this: $$2 * (2 * (4 - 1)) = 12$$
var power = function( base, exponent ) {
if ( exponent === 0 ) return 1;
return base * power( base, exponent - 1 );
};
power(2,4);
===> 16
Obviously I must be reading the function wrong. But how?
Your function is correctly written and you could start by analyzing the result of the function as the recursion advances and the exponent decreases.
Parameters: 2, 4. Result: 2 * power (2, 3) = 2 * 8 = 16.
Parameters: 2, 3. Result: 2 * power (2, 2) = 2 * 4 = 8.
Parameters: 2, 2. Result: 2 * power (2, 1) = 2 * 2 = 4.
Parameters: 2, 1. Result: 2 * power (2, 0) = 2 * 1 = 1.
Parameters: 2, 0. Result: 1.
Hope that was helpful.
This recursively returns 16. If $function$ is represented by $f$:
f(2, 4)=2*f(2, 3)=\dots=2*2*2*2*f(2, 0)=2*2*2*2*1=16
More generally,
f(a, b)=a*...*a*1 <- n times.
It might help to consider how the function behaves, beginning from the end.
So when the exponent equals $0$ it will return $1$, this will be taken times the base, and all of this will again be multiplied by the base, and so on, so:
$$
(((2^0*2)*2)*2)\ldots)*2
$$
The key is recursion.
power(2,4)
= 2 * power(2,3)
= 2 * (2 * power(2,2))
= 2 * (2 * (2 * power(2,1)))
= 2 * (2 * (2 * (2)))
= 16
power calls itself with a smaller exponent, which calls itself etc until the exponent is 1, for which the answer is just the base.