递归幂函数:如果没有初始返回值,为什么这会起作用?

时间:2011-10-05 05:57:56

标签: javascript recursion logic return-value exponential

因为幂(base,exponent)没有返回值,除非exponent为0,最初,不应该power(base,exponent -1)返回'undefined',因此最初是不可复制的?因此,我无法遵循此代码的逻辑。为什么/如何运作?

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

5 个答案:

答案 0 :(得分:8)

看看如果您尝试计算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.

答案 1 :(得分:4)

它可以更简洁:

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

Howerver iterative solution非常快:

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

答案 2 :(得分:1)

我觉得这个功能反过来更有意义,比如:

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

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

答案 3 :(得分:0)

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

答案 4 :(得分: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。