递归函数-阶乘

时间:2019-03-15 02:39:17

标签: function recursion factorial

我正试图将递归函数的阶乘calc示例包住,当试图跟踪递归函数本身的流程时,我总是迷路。它是否为每次迭代都返回*(a-1)的值?为什么不返回值1?简单的单词只能在这里显示:)

// 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;
}

3 个答案:

答案 0 :(得分:0)

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

factorial(3)

在阶乘函数中,变量a的值为3。因此if条件的值为true。这意味着可以将整个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条件为false。这意味着可以将其重写为1:

(3 * 2 * 1)

然后评估3 * 2

(6 * 1)

然后评估6 * 1

(6)

括号在这里无关紧要(但是代码中包含了括号),因此实际上是:

 6

答案 1 :(得分:0)

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

  

当<= 1时返回1

一个递归函数依赖于Stack,当您调用阶乘(9)时,该函数实际上说“哎呀,我还没有答案,但是我知道阶乘(9)实际上是9 *阶乘(9-1)请原谅,我现在要打电话给factorial(8),等以后是否有实际的工作。”

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

答案 2 :(得分:0)

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

这是您必须进行信仰的递归飞跃的地方-“如果我可以信任此功能为我提供较小问题的正确答案,那么我可以为当前问题构建答案。”对于阶乘,对于n等于0或1的正确答案是1,对于n * factorial(n - 1)则是n > 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!.
}

如果您愿意进行信仰的递归飞跃,那么实际上可以编写很多其他非常复杂的函数。