我正试图将递归函数的阶乘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;
}
答案 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!.
}
如果您愿意进行信仰的递归飞跃,那么实际上可以编写很多其他非常复杂的函数。