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" 的一种函数式技术,但我们不会使用 ri 等中间值来计算答案。在函数式风格中,我们也避免了像 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