简体   繁体   English

递归幂 function:如果没有初始返回值,为什么会这样?

[英]Recursive power function: Why does this work if there's no initial return value?

because power(base, exponent) has no return value unless exponent is 0, initially, shouldn't power(base, exponent -1) return 'undefined', and therefore be unmultipliable, initially?因为 power(base, exponent) 没有返回值,除非 exponent 为 0,所以最初,power(base, exponent -1) 不应该返回“未定义”,因此最初是不可乘的吗? So, I am having trouble following the logic of this code.所以,我在遵循这段代码的逻辑时遇到了麻烦。 Why/how does it work?为什么/它是如何工作的?

function power(base, exponent) {
  if (exponent == 0)
    return 1;
  else
    return base * power(base, exponent - 1);
}

Look at what happens if you try to calculate 5^3 :看看如果您尝试计算5^3会发生什么:

power(5, 3)  ... this should give us 125, let's see if it does...

function power(base, exponent) {    // base = 5, exponent = 3
  if (exponent == 0)                // nope, exponent != 0
    return 1;
  else
    return base * power(base, exponent - 1);  // return 5 * power(5, 2)
}

... what is power(5, 2) ? ... 什么是power(5, 2) ... ...

function power(base, exponent) {    // base = 5, exponent = 2
  if (exponent == 0)                // nope, exponent != 0
    return 1;
  else
    return base * power(base, exponent - 1);  // return 5 * power(5, 1)
}

... what is power(5, 1) ? ...什么是power(5, 1) ... ...

function power(base, exponent) {    // base = 5, exponent = 1
  if (exponent == 0)                // nope, exponent != 0
    return 1;
  else
    return base * power(base, exponent - 1);  // return 5 * power(5, 0)
}

... what is power(5, 0) ? ...什么是power(5, 0) ... ...

function power(base, exponent) {    // base = 5, exponent = 0
  if (exponent == 0)                // yup, exponent != 0
    return 1;                       // return 1
  else
    return base * power(base, exponent - 1);
}

... putting that together, in reverse order as we walk back up the stack... ...将它们放在一起,当我们走回堆栈时以相反的顺序......

power(5, 0) = returns 1
power(5, 1) = 5 * power(5, 0) = 5 * 1 =  returns 5
power(5, 2) = 5 * power(5, 1) = 5 * 5 =  returns 25
power(5, 3) = 5 * power(5, 2) = 5 * 25 =  returns 125

... so, power(5, 3) returns 125, as it should.

It could be more concise:它可以更简洁:

function power(base, exponent) {
  return exponent == 0? 1 : base * power(base, --exponent);
}

Howerver an iterative solution is very much faster:然而,迭代解决方案要快得多:

function powerNR(base, exp) {
  var result = 1;
  while(exp--) {
    result *= base;
  }
  return result;
}

I think the function makes more sense the other way around, like this:我认为这个函数反过来更有意义,像这样:

const power = (base, exponent) => {
  if (exponent !== 0) {
    return base * power(base, exponent - 1);
  } else {
    return 1;
  }
}

The return of the if statements are chained together and cannot be resolved until the else statement is executed. if 语句返回被链接在一起,并且在执行else 语句之前无法解析。

Examples例子

4^0 = else;
4^0 = 1

4^1 = if * else;
4^1 = 4 * 1;

4^2 = if * if * else;
4^2 = 4 * 4 * 1;
    = 4 * 4;
    = 16

// Another way of conceptualising it:

4^2 = if(if(else));
    = 4(4(1));
    = 16;

Remember it is the return of the if/else statements that is being passed back up the chain to the function that called it.请记住,它是if/else 语句返回,被传递回链到调用它的函数。

A slightly stupid metaphor一个略显愚蠢的比喻

Let's say you want to ask David a question but you don't want to yell, you could ask there person beside you, who could ask the person beside you, who could ask the person beside you, and so on, until the question was asked to David.假设你想问大卫一个问题但你不想大喊大叫,你可以问你旁边的人,谁可以问你旁边的人,谁可以问你旁边的人,等等,直到问题是问大卫。

const askDavidAQuestion = peopleInBetweenYouAndDavid => {

if (peopleInBetweenYouAndDavid !== 0) {

  console.log('I will ask him');

  return askDavidAQuestion(peopleInBetweenYouAndDavid - 1);

} else {

  console.log('David says no');

}
}

askDavidAQuestion(3);

-> I will ask him
   I will ask him
   I will ask him
   David says no

Only once David's answer is known can that piece of information be passed back up the chain of people that asked the question.只有知道 David 的答案后,这条信息才能在提出问题的人链中传回。

A stack of calls to the function is created.创建了对该函数的调用堆栈。 This process continues until it meets a termination condition/"base case" - here, a returned value.这个过程一直持续到它满足终止条件/“基本情况”——这里是一个返回值。 At that point, all the functions can return and the original function call returns the answer.此时,所有函数都可以返回并且原始函数调用返回答案。 Explained in other terms, the returned values are popped out of the stack and used to calculate the next step (in inverse order) and so forth until the stack is empty.换句话说,返回值从堆栈中弹出并用于计算下一步(以相反的顺序),依此类推,直到堆栈为空。

Using a 2^2 example:使用2^2示例:

power(2, 2); calls:调用:

function power(2, 2) {
    if (2 === 0) {
        return 1;
    } else {
        return 2 * power(2, 1); // Called (waits in line to be solved)
    }
}

This leads to:这将导致:

function power(2, 1) {
    if (1 === 0) {
        return 1;
    } else {
        return 2 * power(2, 0); // Called (waits in line to be solved)
    }
}

This leads to:这将导致:

function power(2, 0) {
    if (0 === 0) {
        return 1; // Returned (previous calls to recursive case can now be solved)
    } else {
        return 2 * power(2, -1);
    }
}

Now that it has a returned value to work with, it can work back outward, so to speak.现在它有一个返回值可以使用,它可以向外工作,可以这么说。

This leads to:这将导致:

function power(2, 1) {
    if (1 === 0) {
        return 1;
    } else {
        return 2 * 1; // Returned
    }
}

This leads to:这将导致:

function power(2, 2) {
    if (2 === 0) {
        return 1;
    } else {
        return 2 * 2; // Returned
    }
}

which ultimately returns 4, which is 2^2.最终返回 4,即 2^2。

All of the listed versions will not work if the exponent is negative.如果指数为负,所有列出的版本都将不起作用 The right version of realization of Math.pow() should be done like this - Math.pow()的正确实现版本应该这样完成 -

    function pow(num1, num2){
        if (num2 === 0){
          return 1;       
        } 
        else if(num2 < 0){
           num2 = Math.abs(num2); 
           return (1 / pow(num1, num2));
        }

        else if(num2 > 0){
           return num1 * (pow(num1,num2 - 1));
        }
};
function pow(base, exponent) {
    if (exponent === 0) return 1;
    if (exponent > 0) {
        return base * pow(base, exponent - 1)
    } else {
        // handle negative exponent
        return 1 / base * pow(base, exponent + 1)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM