也许以下内容可以帮助您理解。计算机并不关心他是否调用了它只是计算的相同函数。一旦你理解了递归是什么以及为什么它适用于许多事物,比如列表、自然数等,这些事物本身就是按结构递归的,就没有什么神奇的了。
- 定义:0的阶乘是1
- 定义:大于 0 的数 n 的阶乘是该数与其前一个数的阶乘的乘积。
因此
5! = 5*4! = 5*4*3! = 5*4*3*2! = 5*4*3*2*1! = 5*4*3*2*1*0! = 5*4*3*2*1*1 = 120
所以,如果你听说过归纳证明,它是这样的:
- 我们为基本案例证明了一些属性。
- 我们证明,如果属性对 n 为真,那么它对 n 的后继也为真。
- 我们得出结论,这是该属性适用于基本情况和所有后续情况的证明。
示例:通过归纳证明偶数的平方是 4 的倍数!
- 0的平方是0,是4的倍数。
- 设 n 为偶数,其平方 n² 是 4 的倍数。则
(2+n)*(2+n)
= 4+2n+2n+n²
。这是 4 的倍数,因为 n² 根据我们的假设,4 是 1,2n+2n = 4n
也是 4 的倍数,而 4 的倍数之和根据分配律是 4 的倍数:4a + 4b = 4(a+b)
- QED 该属性适用于 0(我们的基本情况)和 (2+n),前提是它适用于 n。因此它适用于 2、4、6、8 .... 和所有其他偶数。
(更简单的证明是观察(2a)²
= 4*a*a
,它是 4 的倍数。)
编写递归程序与通过归纳进行证明非常相似:
- 我们为基本情况编写计算。
- 对于非基本情况,我们知道如何计算结果(例如,我们知道
n! = n * (n-1)!
,所以我们把它写下来,因为我们需要的函数就是我们刚刚写的那个!
- 我们可以得出结论,我们的程序将为基本情况和基本情况的任何后继计算正确的值。如果
678!
仍然没有计算出正确的答案,那么它与我们使用的数据类型int
不太适合大数字的事实有关(或者,换句话说,计算所有 moulo 2^32)并且在此外,软件坚持将可用数字的一半解释为负数。
这样做的原因与计算机硬件或编程语言无关:正如我之前所说,它是手头项目(列表、树、集合、自然数)的递归结构的结果。
新手常犯的错误是忽略基本情况并迷失在复杂性中。我总是建议从基本情况开始,一旦你有了这个,你可以假设这个函数存在,并且可以在更复杂的情况下使用它。