【问题标题】:how does a recursive factorial function know when to stop递归阶乘函数如何知道何时停止
【发布时间】:2017-07-06 06:51:56
【问题描述】:

我试图编写一个递归阶乘函数来练习我的递归并想出了这个:

function test(num){
  return (num * test(num - 1))
}

但是,每当我运行它时,它都会永远循环,并且出现 Range Error: Maximum call stack size exceeded。

但是如果我写它来处理异常,

function factorial(num) {
    if (num < 0) {
        return -1;
    } else if (num === 0) {
        return 1;
    } else {
        return (num * factorial(num - 1));
    }
}

完美运行。

2 个问题。

  1. 为什么第一个不起作用?

  2. 第二个如何知道何时停止运行。如果 num 实际上每次都将其值更改为 -1,最终将达到 0,它应该触发 else if 并返回 1,但如果您运行 factorial(3),它确实返回 6。

【问题讨论】:

  • 第一个总是自称(test())——它没有条件停止。第二个将在num === 0 时停止。
  • 第二个有一个if() 语句,当它到达基本情况时不会递归。这就是递归的本质。
  • 第二个有效,因为即使它返回 1,该结果也会在调用它的函数中乘以 num(其中 num = 1),然后乘以 2,以此类推调用堆栈

标签: javascript algorithm recursion


【解决方案1】:
  1. 递归必须有一个基本情况 - 满足函数停止的条件。

  2. 您将从num 下降到num-1,依此类推,直到0,此时函数满足基本情况:num == 0 并返回 1。从这一点开始,递归展开,并乘以 1*num-(num-1)...num

此外,阶乘仅针对非负整数定义,因此返回 -1 没有多大意义。另一件事:基本情况应该是num == 1

你正在做的是乘以1,当num ==1,然后再乘以1,当num == 0factorial(0).返回错误的阶乘

编辑:阶乘(0)为 1。所以,您返回 1 确实是正确的,但我仍将其视为极端情况。无需等待额外的步骤即可到达 0。

function factorial(n){
    // Handle the corner cases: you might as well just throw an error
    if (n < 0) return undefined;
    if (n == 0) return 1;

    // Base case
    if (n == 1) return 1;

    // Iterative step
    // (If the function got to this point, it means, that n > 1)
    return n * factorial(n - 1);

    // In order to return the expression on the right side of "return",
    // You need to calculate the `factorial(n - 1)`
    // When you try calculating it, you will see, that now you need to
    //     find out the `factorial(n - 1)` again, but this time the 
    //     `n` is actually `(n - 1)` :)
    // So this way, you are digging into the call stack.
    // At some point you reach the 1. WHICH RETURNS 1. WOOHOO.
    // No need to calculate the `factorial` anymore.
    // Now all the expressions you couldn't evaluate, get evaluated 1 by 1
}

【讨论】:

  • 很好地描述了递归的过程。谢谢。我仍然很难理解,但这是我见过的最好的解释。现在有点道理。哈哈。我只需要更多地使用它们,直到它们开始有意义
  • @nwimmer123 我已经更新了一些描述,希望更清楚。
猜你喜欢
  • 2021-09-26
  • 2019-08-06
  • 1970-01-01
  • 2015-04-16
  • 2015-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
相关资源
最近更新 更多