我正在尝试编写一个递归因子函数来练习我的递归,并想出了这个:
function test(num){
return (num * test(num - 1))
}
但是,无论何时运行它,它都会永远循环,我得到一个范围错误:超出最大调用堆栈大小。
但如果我写它来处理异常,
function factorial(num) {
if (num < 0) {
return -1;
} else if (num === 0) {
return 1;
} else {
return (num * factorial(num - 1));
}
}
完美无缺。
2个问题。
为什么第一个不起作用?
第二个如何知道何时停止运行。如果num实际上每次将它的值改为-1,它最终会达到0并且它应该触发else if并返回1,但是如果你运行factorial(3)它会返回6.
答案 0 :(得分:2)
递归必须具有基本情况 - 函数停止时遇到的条件。
您将从num
转到num-1
,依此类推,直至0
,此时该函数符合基本情况:num == 0
并返回1从这一点开始,递归展开,并乘以1 * num-(num-1)
... num
。
此外,factorial仅针对非负整数定义,因此返回-1
时没有太大意义。另一件事:基本情况应该是num == 1
。
当您1
时,您正在做的是乘以num ==1
,然后再乘以1
num == 0
。 返回 factorial(0).
编辑:factorial(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
}