【问题标题】:Recursive functions - factorials递归函数 - 阶乘
【发布时间】:2019-08-06 01:43:31
【问题描述】:

我试图围绕递归函数的阶乘计算示例展开思考,但在尝试跟踪递归函数本身的流程时,我总是会迷失方向。它是否为每次迭代返回 a * (a - 1) 的值?为什么它不返回值 1?简单的词请在这里newb :)

// factorial calculator
#include <iostream>
using namespace std;

long factorial (long a)
{
  if (a > 1)
   return (a * factorial (a-1));
  else
   return 1;
}

int main ()
{
  long number = 9;
  cout << number << "! = " << factorial (number);
  return 0;
}

【问题讨论】:

    标签: function recursion factorial


    【解决方案1】:

    停止尝试通过递归调用跟踪所有内容,并将递归函数视为实际上是一个函数。它只是碰巧有时会调用自己。当您向函数传递参数时,您不需要知道墙后发生了什么。函数是正在完成的工作的抽象,并根据其参数返回正确答案。例如,当您使用exp()log()cos() 时,您无需知道它的实际工作原理即可使用它。

    这就是你必须实现信念的递归飞跃的地方——“如果我可以相信这个函数能够为我提供一个较小问题的正确答案,那么我就可以为我当前的问题构建答案。”对于阶乘,正确答案是 1 代表 n 等于 0 或 1,它是 n * factorial(n - 1) 代表 n &gt; 1。您可以通过为一个小案例编写该公式来确认这一点:

    4! = 4 * 3! = 4 * (3 * 2!) = 4 * (3 * (2 * 1!)) = 4 * (3 * (2 * 1))

    是的,这几乎就是 4 的算术定义!。

    现在看你贴的递归实现,稍微重新排序,直接对应:

    long factorial(long a) {  // If I trust this function...
      if (a <= 1)   // when a is 0 or 1
        return 1;   // I know the answer is 1.
      else          // Otherwise, trust the answer for the smaller case of (a-1) and 
        return (a * factorial(a-1));         // multiply that answer by a to get a!.
    }
    

    如果您愿意做出这种递归式的信念飞跃,那么许多原本非常复杂的函数实际上都是自己编写的。

    【讨论】:

      【解决方案2】:

      因为该方法正在调用自身,因此它被称为递归。递归函数必须有一个在满足条件时停止执行的代码,例如在您的代码中,它是

      一个递归函数依赖于堆栈,当你调用阶乘(9)时,函数实际上说“哎呀,我还没有答案,但我知道阶乘(9)实际上是9 *阶乘(9-1) . 所以对不起,我现在要调用 factorial(8) 并等待将来是否有任何实际工作"

      然后代码最终遇到了 factorial(1),然后它停止并说“1 的阶乘本身就是 1”,它非常清楚这一点,我称之为递归函数的停止点。

      【讨论】:

        【解决方案3】:

        假设您正在重写正在评估的代码行。例如,假设您调用:

        factorial(3)
        

        在阶乘函数中,您的变量 a 的值为 3。因此 if 条件的计算结果为真。这意味着您的整个 if 语句可以重写为 return (a * factorial (a-1)),但用值 3 替换 a。所以你有:

        (3 * factorial (3-1))
        

        继续,3-1 将被评估离开:

        (3 * factorial (2))
        

        下一步是评估对factorial(2) 的调用。在此调用中,变量 a 的值为 2,因此 if 条件再次评估为 true,并且可以重写为:

        (3 * 2 * factorial(2-1))
        

        然后2-1 被评估,所以你得到:

        (3 * 2 * factorial(1))
        

        然后评估对factorial(1) 的调用。这次a 的值为 1,if 条件为假。这意味着它可以重写为 1:

        (3 * 2 * 1)
        

        然后评估3 * 2

        (6 * 1)
        

        然后评估6 * 1

        (6)
        

        括号在这里无关紧要(但你的代码中有它们)所以实际上是:

         6
        

        【讨论】:

        • 这是我一直在寻找的解释。谢谢,我一直认为递归函数本身只会一直循环直到它达到 1 并且只返回一个值 1,我跳过了它实际存储的部分 (6*5*4*..(a-1))
        猜你喜欢
        • 1970-01-01
        • 2015-04-16
        • 1970-01-01
        • 2017-05-07
        • 2012-04-01
        • 2015-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多