5

因为 power(base, exponent) 没有返回值,除非 exponent 为 0,所以最初,power(base, exponent -1) 不应该返回“未定义”,因此最初是不可乘的吗?所以,我在遵循这段代码的逻辑时遇到了麻烦。为什么/它是如何工作的?

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

5 回答 5

10

看看如果你尝试计算会发生什么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)
}

... 是什么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)
}

... 是什么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)
}

... 是什么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);
}

......把它们放在一起,当我们回到堆栈时,以相反的顺序......

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.
于 2011-10-05T06:11:14.143 回答
6

它可以更简洁:

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

然而,迭代解决方案要快得多:

function powerNR(base, exp) {
  var result = 1;
  while(exp--) {
    result *= base;
  }
  return result;
}
于 2011-10-05T06:39:15.233 回答
2

我认为这个函数反过来更有意义,就像这样:

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

if 语句返回链接在一起,直到执行else 语句才能解决。

例子

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;

请记住,将if/else 语句返回值沿链传递回调用它的函数。

一个略显愚蠢的比喻

假设你想问大卫一个问题但你不想大喊大叫,你可以问你旁边的人,谁可以问你旁边的人,谁可以问你旁边的人,等等,直到问题是问大卫。

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

只有知道大卫的答案后,才能将这条信息传递回提出问题的人的链条中。

于 2018-04-16T11:54:56.467 回答
0

创建了对该函数的调用堆栈。这个过程一直持续到它满足终止条件/“基本情况”——这里是一个返回值。此时,所有函数都可以返回,原始函数调用返回答案。换句话说,返回的值从堆栈中弹出并用于计算下一步(以相反的顺序)等等,直到堆栈为空。

使用2^2示例:

power(2, 2); 调用:

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

这将导致:

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

这将导致:

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);
    }
}

现在它有一个可以使用的返回值,可以这么说,它可以向外工作。

这将导致:

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

这将导致:

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

最终返回 4,即 2^2。

于 2021-04-21T22:52:07.343 回答
-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)
    }
}
于 2020-01-06T20:08:27.160 回答