JavaScript 中的因式分解仅适用于递减递归,为什么?
Factorialization in JavaScript only works with decreasing recursion, why?
JavaScript 中的阶乘函数仅适用于递减递归 (i--)。如果我使用 i++ (Google Chrome),函数被调用但没有返回结果,几乎就像我会开始一个无限循环一样。我的代码哪里出错了?
This code does not work:
function factorial(n) {
if (n == 0 || n == 1) {
return 1;
}
for (var i = 1; i < n; i++) {
n *= i;
}
return n;
}
This code works:
function factorial(n) {
for (var i = n - 1; i >= 1; i--) {
n *= i;
}
return n;
}
这是因为在您的 for 循环条件中您正在进行 i < n
比较。 n 值的上升速度快于 i 值(因为 n 在每次迭代中相乘,而 i 递增)从而形成无限循环。您可以通过使用不同的变量将结果存储在以下位置来解决此问题:
function factorial(n) {
var r = n;
if (n == 0 || n == 1) {
return 1;
}
for (var i = 1; i < n; i++) {
r *= i;
}
return r;
}
您的代码的替代版本(使用递减迭代器)不会发生所描述的情况,因为它的循环条件 (i >= 1
) 不使用在每次迭代中更改的 n 值。
另外请记住,您发布的两个函数都不是递归的。它们都是迭代的(第一个迭代器递增,另一个迭代器递减)。
您的问题使用 imperatives-style for
循环,但您使用递归标记了 post。您在寻找使用递归的解决方案吗?
递归是 "looping" 的一种函数式技术,但我们不会使用 r
和 i
等中间值来计算答案。在函数式风格中,我们也避免了像 i++
这样的突变和像 r *= i
这样的重新评估。相反,我们以更直接的方式编码我们的意图 -
const fact = (n = 0) => {
if (n === 0)
return 1 // (base) n is zero
else
return n * fact(n - 1) // (inductive) n is greater than zero
}
console.log(fact(5)) // 120
console.log(fact(10)) // 3628800
我们可以删除 imperative-style if-else
语句并将其替换为 functional-style 表达式 -
const fact = (n = 0) =>
n === 0
? 1 // (base) n is zero
: n * fact(n - 1) // (inductive) n is greater than zero
console.log(fact(5)) // 120
console.log(fact(10)) // 3628800
最后,我们使用"increasing"递归计算-
const fact = (n = 0, a = 1) =>
a >= n
? a // (base) a >= n
: a * fact(n, a + 1) // (inductive) a < n
console.log(fact(5)) // 120
console.log(fact(10)) // 3628800
JavaScript 中的阶乘函数仅适用于递减递归 (i--)。如果我使用 i++ (Google Chrome),函数被调用但没有返回结果,几乎就像我会开始一个无限循环一样。我的代码哪里出错了?
This code does not work:
function factorial(n) {
if (n == 0 || n == 1) {
return 1;
}
for (var i = 1; i < n; i++) {
n *= i;
}
return n;
}
This code works:
function factorial(n) {
for (var i = n - 1; i >= 1; i--) {
n *= i;
}
return n;
}
这是因为在您的 for 循环条件中您正在进行 i < n
比较。 n 值的上升速度快于 i 值(因为 n 在每次迭代中相乘,而 i 递增)从而形成无限循环。您可以通过使用不同的变量将结果存储在以下位置来解决此问题:
function factorial(n) {
var r = n;
if (n == 0 || n == 1) {
return 1;
}
for (var i = 1; i < n; i++) {
r *= i;
}
return r;
}
您的代码的替代版本(使用递减迭代器)不会发生所描述的情况,因为它的循环条件 (i >= 1
) 不使用在每次迭代中更改的 n 值。
另外请记住,您发布的两个函数都不是递归的。它们都是迭代的(第一个迭代器递增,另一个迭代器递减)。
您的问题使用 imperatives-style for
循环,但您使用递归标记了 post。您在寻找使用递归的解决方案吗?
递归是 "looping" 的一种函数式技术,但我们不会使用 r
和 i
等中间值来计算答案。在函数式风格中,我们也避免了像 i++
这样的突变和像 r *= i
这样的重新评估。相反,我们以更直接的方式编码我们的意图 -
const fact = (n = 0) => {
if (n === 0)
return 1 // (base) n is zero
else
return n * fact(n - 1) // (inductive) n is greater than zero
}
console.log(fact(5)) // 120
console.log(fact(10)) // 3628800
我们可以删除 imperative-style if-else
语句并将其替换为 functional-style 表达式 -
const fact = (n = 0) =>
n === 0
? 1 // (base) n is zero
: n * fact(n - 1) // (inductive) n is greater than zero
console.log(fact(5)) // 120
console.log(fact(10)) // 3628800
最后,我们使用"increasing"递归计算-
const fact = (n = 0, a = 1) =>
a >= n
? a // (base) a >= n
: a * fact(n, a + 1) // (inductive) a < n
console.log(fact(5)) // 120
console.log(fact(10)) // 3628800