【问题标题】:Recursive power function: Why does this work if there's no initial return value?递归幂函数:如果没有初始返回值,为什么会这样?
【发布时间】:2011-12-01 05:12:58
【问题描述】:

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

【问题讨论】:

  • 嗯,它从 if 中返回两种情况下的值。真的看不出你有什么问题。
  • power(13, 5) = 13*(13*(13*(13*(13*power(13, 0)))))。最终值仅在最后一次 power() 调用之后 计算。该函数计算 power(13, 0) 是 1,然后是 13*1,然后是 13*(13)...
  • 哦。你应该提交那个。这是有道理的。

标签: javascript recursion logic return-value exponential


【解决方案1】:

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

【讨论】:

  • 哦。我就是这么想的,但这只是一种预感。这样写出来就更美了。谢谢你。不过,我能问一下是什么导致它往回走吗?
  • 如果在到达0之前没有返回值,那么它必须从0返回到3并且每次都接收返回,对吗?或者是否有返回值加起来到 0,我们可以列出并“遍历”?很抱歉造成混乱,但我真的不知道“步行”是否意味着程序正在运行数字,或者是否意味着人们可以看到它们,因为它们存在。是技术术语还是什么?
  • 啊,我明白了。因为它是未定义的,所以它只是乘以 13*undefined*13(结果为 13*13),然后最后将结果乘以 1,并因为返回而结束程序。所以,我猜,走路意味着精神上的。酷。
【解决方案2】:

可以更简洁:

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

不过iterative solution 更快:

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

【讨论】:

  • 是否:表示其他和?意思是'如果是,返回以下'?
  • 三元运算符为:(test)? <if true return this> : <if false return this>,等价于:if(test){do something}else{do something else}
  • 迭代函数更快,因为它只有一个函数调用,递归函数有多个调用(对自身)。函数调用相对昂贵,尽可能避免它们。递归函数可以非常简洁,但这不一定是使用它们的好理由。它们通常难以阅读且速度缓慢(但当您想用少量代码完成大量工作时,它们看起来真的很酷)。
  • 太棒了。感谢您及时通知我,RobG。
  • 请注意,这些实现不处理负指数。 OP 给出的例子也不是,所以我不确定这有什么大不了,但对于那些希望同时处理负指数和正指数的人来说,值得注意。
【解决方案3】:

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

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

if 语句return 链接在一起,直到 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 语句return 被沿链向上传递给调用它的函数。

有点愚蠢的比喻

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

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

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

【讨论】:

    【解决方案4】:

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

    使用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。

    【讨论】:

      【解决方案5】:
      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)
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-11-20
        • 1970-01-01
        • 2018-09-03
        • 2022-12-06
        • 1970-01-01
        • 2015-03-21
        • 2012-09-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多