Eloquent JavaScript: Can't understand recursion example [duplicate] - javascript

This question already has answers here:
How does Eloquent JavaScript recursion example terminate as return 1 but still output exponential value
(2 answers)
Closed 7 years ago.
From page 50 of Haverbeke's second edition. I added a couple of console.log to try to better track the progress.
function power(base, exponent) {
if (exponent == 0) {
console.log("line 5 " + base + " " + exponent);
return 1;
}
else
console.log("line 10 " + base + " " + exponent);
return base * power(base, exponent -1);
}
console.log(power(2,3));
// Output
line 10 2 3
line 10 2 2
line 10 2 1
line 5 2 0
8
//
I expect the final output to be 1 since when the if (exponent == 0) is true, the next statement is return 1;, but it appears to enter the else one more time to return 8. But shouldn't the return kick us out of the function.
Obviously a newbie or wouldn't be stuck on page 50 of a supposedly beginner book.
Thanks for any help.

Whenever the function enters the "else" branch, a new stack frame is created, waiting for the result of the recursive call. You can imagine the evaluation step by step:
power(2, 3) enters the else branch, and it returns base * power(base, exponent - 1).
2 * power (2, 2) enters the else branch, and it returns base * power(base, exponent - 1).
2 * (2 * power (2, 1)) enters the else branch, and it returns base * power(base, exponent - 1).
2 * (2 * (2 * power (2, 0))) enters the if branch, and it returns 1.
You can finally evaluate the result: 2 * (2 * (2 * 1)), which is 8.

The end result of the function call power(2,3) is not the last return, but the combination of returned values, by the subsequent internal function calls. Let's deconstruct the recursive function:
power(2,3) returns 2 * power(2,2)
power(2,2) returns 2 * power(2,1)
power(2,1) returns 2 * power(2,0)
power(2,0) returns 1
So in total, power(2,3) returns 2 * 2 * 2 * 1 which is equal to 8.

The return statement exits from one invocation of the function. In order to get to the return 1; line, the function will have been called several times (based on the original value of the exponent).
The first invocation is
console.log(power(2,3));
Inside the function, subsequent invocations take place here:
return base * power(base, exponent -1);
Each one will correspond with a return.
Oh, and as #TJCrowder notes in a comment, that code is not correct: the else part should be wrapped in { }:
if (exponent == 0) {
console.log("line 5 " + base + " " + exponent);
return 1;
}
else {
console.log("line 10 " + base + " " + exponent);
return base * power(base, exponent -1);
}
I'm assuming that the missing { } wrapper was a transcription error.

Related

Confusion in eloquent javascript power recursion sample

this recursion code is from the book of eloquent javascript
function power(base, exponent) {
if (exponent == 0) {
return 1;
}
else {
return base * power(base, exponent - 1);
}
}
console.log(power(2, 3));
obviously the exponent is decreased until it reached 0, if it is not zero, it adds power call on the stack, if it is zero, I start to see the return value of 1 then 2 then 4 then 8. But how did base got multiplied by exponent, how did base see the exponent value? it's on else and on power call?
But how did base got multiplied by exponent
It doesn't multiply by the exponent.
The exponent is being used as a counter to end the recursive cycle once it's been reduced to 0. The base is instead being multiplied by itself an exponent number of times.
This is supported by each call to power() returning either 1 or the value of base. In the latter case, power() is called again to get 1 or another copy of base to multiply by. And, this repeats until it does finally return 1 as the final multiplier.
power(2, 3) ==
2 * power(2, 2) == // base * ...
2 * 2 * power(2, 1) == // base * (base * ...)
2 * 2 * 2 * power(2, 0) == // base * (base * (base * ...))
2 * 2 * 2 * 1 // base * (base * (base * (1)))
The same steps could also be defined with a loop, though using 1 as the initial value rather then at the end:
function power(base, exponent) {
var result = 1;
while (exponent) {
result *= base;
exponent--;
}
return result;
}
console.log(power(2, 3)); // 1 * base * base * base == 1 * 2 * 2 * 2 == 8
I find it easy to understand recursive procedures by looking at their base case first, then building up from there – here's the function we're studying...
function power(base, exponent) {
if (exponent == 0) {
return 1;
}
else {
return base * power(base, exponent - 1);
}
}
So here, the base case is exponent == 0. We'll keep 2 as the input for base:
power(2, 0) => 1
Well that was really easy! All we had to do was evaluate an if statement and we arrived at our answer. Looking ahead, we see that power arrives at its base case by subtracting 1 from the exponent (exponent - 1), we'll reverse this to get our next input – so instead of power(2, 0) we will do power(2, 1)
power(2, 1) => 2 * power(2, 0)
=> but wait! don't re-evaluate power(2,0)! we already know that answer from above
=> 2 * 1
=> 2
Ok, we'll keep doing the same thing by incrementing exponent by 1 each time. But be careful not to do unnecessary work – if we've already evaluated one of the expressions earlier, just replace that expression with it's evaluated value
power(2,2) => 2 * power(2, 1)
=> we already know power(2,1) == 2 ...
=> 2 * 2
=> 4
power(2,3) => 2 * power(2,2)
=> we already know power(2,2) == 4, etc
=> 2 * 4
=> 8
power(2,4) => 2 * power(2,3)
=> 2 * 8
=> 16
power(2,5) => 2 * power(2,4)
=> 2 * 16
=> 32
Now we can easily see a pattern and how the recursive procedure works in general
What you have to notice is that the power function
returns 1 when exponent is 0 and
return base * power() on another case.
Pay attention to power function
In the following code
power(base, exponent - 1);
you have to appreciate some things
1) If exponent is 1 the function power returns 1 so in here
return base * power(base, exponent - 1);
Whether base is 2
return 2 * 1
The function power is returning 2, so in the next step
return base * power(base, exponent - 1);
means
return 2 * 2;
which is 4, that means that function power is returning 4
I think you can catch up from here.
Let me know if you understood :)

Return 1 in javascript [duplicate]

This question already has answers here:
Recursive power function: Why does this work if there's no initial return value?
(6 answers)
Closed 8 years ago.
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
If I change it to return 2, it doubles the answer, 3 triples etc.
I understand what it's doing, but I haven't learned how it knows to produce a multiple of the return from the 'else' part. Please explain.
EDIT: While I'm here, how is the else working? I would assume base is being multiplied by base, and then the exponent is subtracting from itself, but when I do something like: base * (2, 5-1) it multiplies base by 4... I must be missing something simple.
If you return 1, then calling power(7, 3) will result in:
7 * 7 * 7 * 1
If you return 2, then it will result in:
7 * 7 * 7 * 2
where the last number is the number that you are returning.
Do you now see why changing the return value doubles the result?
To answer your second question, this due to the behavior of the comma operator, which evaluates to the value of the expression after the last comma so:
base * (2, 5 - 1)
base * (5 - 1)
base * (4)
This is completely unrelated to calling a function with the parameters 2 and 5 - 1.
It doesn’t have to "know" anything. It keeps recurring until the exponent is zero.
how is the else working?
If exponent != 0 it runs, its the opposite of the if.
This is a recursive function that calls itself over and over until it finds the correct answer. Tracing the way the function works should help you understand it.
Take power(2, 5) for example.
power(2, 5) = 2 * power(2, 4)
= 2 * 2 * power(2, 3)
= 2 * 2 * 2 * power(2, 2)
= 2 * 2 * 2 * 2 * power(2, 1)
= 2 * 2 * 2 * 2 * 2 * power(2, 0)
= 2 * 2 * 2 * 2 * 2 * 1
All together, you end up with 2 * 2 * 2 * 2 * 2 * 1 which is 25, as expected. The else in your function gets triggered when the exponent parameter (the 5 in the example) is greater than zero. Since 5 is greater than 0, the else part is triggered and the function is called again with 4 as the exponent. Since 4 is greater than 0, the else part is triggered and the function is called again with 3 as the exponent. The same thing happens with 2, then 1, then 0. When power(2, 0) is finally called, the function just returns 1.

Need help understanding recursive function example from Eloquent Javascript

function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
I think that I understand the basic principle of recursion, it simply means you are calling the function within the function itself. This can be used to perform a loop of sorts, but what I cant figure out is how the above code actually decides to loop in order to figure out the exponential value of a number. I used function power(2,5) as my argument and the function knew the answer was 32, but how? Does the function loop itself subtracting 1 from the exponent each time, and multiplying base * base until exponent reaches zero? And if thats the case, how does calling the power function within the function accomplish this exactly? And once exponent reaches zero, wouldnt the function then just return 1 and not the correct answer?
I consider each recursive step (the function calling itself) producing a shorter and easier problem.
The easiest problem is power(base, 0), which satisfies exponent == 0 and returns one (any base to the zeroth power is 1).
Then, notice that no matter how large exponent is, it is reducing exponent by one, guaranteeing that it will eventually reach the "easiest" problem where the exponent is zero. It only can't be negative, or else this "base case" is never reached.
So, 2^5, or power(2, 5), becomes 2 * 2^4. And 2^4 = 2 * 2^3. By continuing this expansion, we get 2 * 2 * 2 * 2 * 2 * 1, which equals 32. The 1 represents the case exponent == 0 being true.
The computation has to keep track how many of these multiplications it has accumulated, and once the base case of exponent == 0 is reached, multiply all numbers together. It cannot know in advance with certainty what power(base, exponent-1) will return.
Follow the call pattern.. Let's assume we do power(2,2).. You get this:
power(2,2) -> (exponent != 0) 2 * power(2, 1)
2 * power(2, 1) -> (exponent != 0) 2 * power(2, 0)
2 * 2 * power(2,0) -> (exponent == 0) 1
2 * 2 * 1 = 4
The way it works is basically your call stack, as long as you keep calling sub-methods, your parent doesn't return. So it keeps nesting itself until it hits a concrete # -- in this case, 1, then it goes back up the stack actually doing the *.
This shows intermediate results which may help you to follow the logic:
Each level has its own value of base, exponent, answer.
function power(base, exponent) {
var answer; // local
level = level + 1;
console.log("Entering: power(" + base + ", " + exponent +
") (level " + level + ")");
if (exponent == 0) { // don't recurse any more
answer = 1; }
else { // recurse to get answer
answer = base * power(base, exponent - 1); }
// now return answer
console.log("Leaving: power("+ base + ", " + exponent +
") (level " + level + ") ans=" + answer);
level = level - 1
return answer;
}
var level = 0; // global
console.log("Final answer: " + power(2, 5));
The best way to explain the above recursive is to see what the console returns
function power(base, exponent) {
// termination/base case
if (exponent == 0)
return 1;
// recursive case
else
console.log(base + ':' + exponent)
return base * power(base, exponent - 1);
// 2 * (2, 4) = 4
// 4 * (2, 3) = 8
// 8 * (2, 2) = 16
// 16 *(2, 1) = 32
// 16 *(2, 0) = 1 recursive stops and returns 1
// function calls the last return = 32
}
var result = power(2,10)
console.log(result)
I hope this give you a more visual view of how this recursive works
This also confused heck out of me when i first saw it, after 10 minutes starring at it, it just came to me....nothing magical....
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
console.log(power(2, 5));
this is how it runs through:
return base * power(base, exponent - 1)
looking at the above line itself, I was lost too. there are no operations(+,-,*,/,%) done to the given parameters 2 and 5, but somehow at the end, console.log just know to produce correct number.
Because it does not return a numeric value, it simply returns base * power(base, exponent -1) itself, when program reaches power(base, exponent -1), it executes it before return happens, until exponent == 0 becomes true.
1st:
return base * power(base, 5 - 1);
2nd:
return base * base * power(base, 4 - 1);
3rd:
return base * base * base * power(base, 3 - 1);
4th:
return base * base * base * base * power(base, 2 - 1);
5th:
return base * base * base * base * base * power(base, 1 - 1);
6th:
return base * base * base * base * base * 1;
because if (exponent == 0) return 1
so:
2*2*2*2*2*1 = 32

Can someone please explain this recursive JS code to calculate exponents?

I can't understand this recursion even though it's a really simple example. When it goes to power(base, exponent - 1); what is that supposed to do? How are things being multiplied when power keeps getting invoked until exponent equals 0?
function power(base, exponent) {
if (exponent === 0) {
return 1;
} else {
return base * power(base, exponent - 1);
}
}
Let's start from the beginning.
Let's say you call power(base, 0). Since exponent is 0, the function returns 1.
Now, let's say you call power(base, 1). Since exponent isn't 0 this time, the function calls power(base, exponent - 1) and multiplies it by base. (That's the key here...it takes the result from the recursive call, and adds its own twist.) Since exponent - 1 = 0, and power(base, 0) is 1, the result is effectively base * 1. Read: base.
Now on to power(base, 2). That ends up being base * power(base, 1). And power(base, 1) is base * power(base, 0). End result: base * (base * 1). Read: base squared.
And so on.
In case it wasn't obvious, by the way, this function will only work with non-negative integer exponents. If exponent is negative, or is even the tiniest bit more or less than a whole number, the function will run "forever". (In reality, you'll more than likely cause a stack overflow, once recursion eats up all of your stack.)
You could fix the function for negative powers with some code like
if (exponent < 0) return 1 / power(base, -exponent);
As for non-integers...there's no good way to solve that other than throwing an exception. Raising a number to a non-integer power makes sense, so you don't want to just truncate the exponent or otherwise pretend they didn't try to do it -- you'd end up returning the wrong answer.
This is similar to Math.pow(); it raises the base argument to the exponent argument.
For example, 2 ^ 4 is 16, so power(2, 4) would return 16. The if() statement checks to see whether the exponent (power) is zero and returns 1 if it is - any number raised to the power 0 equals 1.
The last line
return base * power(base, exponent - 1);
Is a recursive function that calls power() from within itself however many times specified by the value in exponent.
I'll try to explain recursion from the bottom up, or "from the middle" shall we say; it's probably easier to understand.
The bottom most call of power() takes 2 and 1 as it's arguments, and will return 1. This return value is then used in the second up call of power(), so this time the arguments passed are 2 and 2, which outputs 4, and so on until the top-most call to power() is passed 2 and 4 which returns 16.
Using a 2^3 example:
power(2, 3);
calls:
function power(2, 3) {
if (3 === 0) {
return 1;
} else {
return 2 * power(2, 2); //called
}
}
which leads to:
function power(2, 2) {
if (2 === 0) {
return 1;
} else {
return 2 * power(2, 1); //called
}
}
which leads to:
function power(2, 1) {
if (1 === 0) {
return 1;
} else {
return 2 * power(2, 0); //called
}
}
which leads to:
function power(2, 0) {
if (1 === 0) {
return 1; //returned
} else {
return 2 * power(2, -1);
}
}
which leads to:
function power(2, 1) {
if (1 === 0) {
return 1;
} else {
return 2 * 1; //returned
}
}
which leads to:
function power(2, 2) {
if (2 === 0) {
return 1;
} else {
return 2 * 2; //returned
}
}
which leads to:
function power(2, 3) {
if (3 === 0) {
return 1;
} else {
return 2 * 4; //returned
}
}
which ultimately returns 8, which is 2^3.
Assuming the initial call is power(10, 3)...
v-----first power() call returns base * (result of next power() call)
v-----second power() call returns base * (result of next power() call)
v-----third power() call returns base * (result of last power() call)
v------result of last power() call returns 1
(10 * (10 * (10 * (1))))
^-----return 1
^-----return base * 1 (10)
^-----return base * 10 (100)
^-----return base * 100 (1000)
Or go down the left, and up the right. Each line is a subsequent call to power() starting with power(10, 3)...
return base * power(base, 2); // return base * 100 (1000)
return base * power(base, 1); // return base * 10 (100)
return base * power(base, 0); // return base * 1 (10)
return 1; // return 1 (1)
base = 10
power = 3
10 * power(10,2)
10 * 10 * power(10,1)
10 * 10 * 10
maybe ok for positive integers...
Let's try to explain this with some maths.
f(x,y) = x^y # (1) function definition
= x * x * x * ... * x # (2) multiply x with itself y times
= x * (x * x * ... * x) # (3) rewrite using parentheses for clarity
= x * (x^(y-1)) # (4) replace the second part by (1) notation
= x * f(x, y-1) # (5) replace again by using f(x,y) notation according to (1)
f(x,0) = 1 # base case: x^0 = 1
Following this you can see that f(x,y) = x * f(x, y-1).
You can also see where
if (exponent === 0) {
return 1;
}
comes from, namely the base case that something to the 0th power always equals 1: f(x,0) = 1.
That's how this recursion was derived.

How exactly does this recursive function work in JavaScript?

I have the following example of a recursive function, and what I don't understand is the order in which things are happening:
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
When does the function return the values, at the end of all the process or each time?
A simple way to visualize what happens in recursion in general is this:
a stack of calls to the function is created: this process needs a proper termination condition to end (otherwise you'll have infinite recursion, which is evil)
the single results are popped out of the stack: each result is used to calculate the next step, until the stack is empty
I.e. if base=5 and exponent=3, the call stack is (last element on top):
5*(5*(5*1))
5*(5*(5*power(5, 0)))
5*(5*power(5, 1))
5*power(5, 2)
power(5, 3)
then every called function has real parameters and is ready to return a value (first element on top):
5*(5*(5*1))
5*(5*5)
5*25
125
Note that here the functions are calulated in inverse order: first power(5, 0), then power(5, 1), and so on.. After each calulation an element of the stack is released (i.e. memory is freed).
Hope it helps :)
It is generally helpful in understanding recursive functions such as this to work things out like you would in an algebra class. Consider:
power(3, 4)
= 3 * power(3, 3)
= 3 * (3 * power(3, 2))
= 3 * (3 * (3 * power(3, 1)))
= 3 * (3 * (3 * (3 * power(3, 0))))
= 3 * (3 * (3 * (3 * 1)))
= 3 * (3 * (3 * 3))
...
= 81
The key here is that power is calling itself exactly in the way it could call any other function. So when it does that, it waits for the function to return and uses its return value.
So if you do
var x = power(10, 2);
Your call to power will get to this line:
return base * power(base, exponent - 1)
...and call power(10, 1), waiting for that to return.
The call to power(10, 1) will, of course, get to the line:
return base * power(base, exponent - 1)
...and call power(10, 0), waiting for that to return.
The call to power(10, 0) will return 1, which is then used by the call in #2 above to complete its work and return 10 * 1 = 10, which will then let your original call in #1 above return the value 10 * 10 = 100.
When seeking to understand things like this, there's nothing quite like walking through the code with a debugger. In this modern world, you have plenty to choose from, many of which may already be on your computer.
For better visualization, just substitute the function call with the function body (may be pseudo code for instance).
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
power(5, 3) expands to this
function power(5, 3) {
// exponent 3 is not 0
// return 5 * power(5, 3-1)
return 5 * function power(5, 2) {
// exponent 2 is not 0
// return 5 * power(5, 2-1)
return 5 * function power(5, 1) {
//exponent 1 is not 0
// return 5 * power(5, 1-1)
return 5 * function power(5, 0){
//exponent 0 is 0
return 1;
}
}
}
}
Now the picture is clear. It all becomes like below..
// 1
function power(5, 3){
return 5 * function power(5, 2){
return 5 * function power(5, 1){
return 5 * ( function power(5, 0){
return 1;
} )
}
}
}
// 2
function power(5, 3){
return 5 * function power(5, 2){
return 5 * ( function power(5, 1){
return 5 * 1;
} )
}
}
// 3
function power(5, 3){
return 5 * ( function power(5, 2){
return 5 * 5 * 1;
} )
}
// 4
function power(5, 3){
return ( 5 * 5 * 5 * 1 );
}
// 5
5 * 5 * 5 * 1;
As with any recursive function, the return from a particular "instance" happens when the return value has been calculated. This means that the recursed versions will then have been calculated.
So if you pass in an exponent of 4, there will be at some point 4 copies of the function being executed at one time.
This line and its resolution really trips me up:
return base * power(base, exponent - 1)
I get that the exponent is decremented until it meets the base case, but when you mulitply
the base times the recursive function call, I keep thinking "how does the function mulitply the base by itself(the base arguement)?", where is it doing that exactly, because calling base * power(base, exponent - 1) doesn't look like the standard loop contruction. How can it be calling a function with two arguements, how does it know to skip the exponent arguement and multiply the base by the base?
From a mathematical perspective:
let x = base,
let n = exponent
x*x^(n-1) = x^n
because
x^1*x^n-1=x^n (exponents of like term adds together)
It is the same as:
base * base*exponent-1.

Categories