c - 递归函数背后的魔力是什么?
问题描述
问题:
你能解释一下这个函数如何返回正确的结果16
吗?
我是编程新手,现在这段代码是递归的,但是我想我迷失了,就像我理解它们一样。尽管如此,我相信我会弄清楚阶乘递归或斐波那契递归。
基础是0
,这很好,但我不知道为什么会得到16
......
我在函数中打印了每个变量并进行了调试,但这些除了麻烦之外没有帮助。当b
variable is 0
(和a
variable is 32
)时,条件得到满足,但为什么它返回 value 16
?我会像经典的阶乘函数示例那样理解一种函数n * fact(n-1)
,但在这里我无法想象递归如何返回预期结果。
代码:
#include <stdio.h>
int fun(int a, int b)
{
if (b == 0)
{
return 0;
}
if (b % 2 == 0)
{
return fun(a+a, b/2);
}
return fun(a+a, b/2)+a;
}
int main()
{
printf("%d\n", fun(4, 4));
return 0;
}
提前致谢!
解决方案
添加打印输出,它会变得非常清晰:
int fun(int a, int b)
{
printf("fun(%d, %d)\n", a, b);
if (b == 0) {
printf("b == 0, returning 0\n");
return 0;
}
if (b % 2 == 0) {
printf("b is even, returning f(%d, %d)\n", a+a, b/2);
return fun(a+a, b/2);
}
printf("b is odd, returning f(%d, %d) + %d\n", a+a, b/2, a);
return fun(a+a, b/2)+a;
}
输出:
$ ./a.out
fun(4, 4)
b is even, returning f(8, 2)
fun(8, 2)
b is even, returning f(16, 1)
fun(16, 1)
b is odd, returning f(32, 0) + 16
fun(32, 0)
b == 0, returning 0
16
所以最终发生的事情是f(16, 1)
返回f(32, 0) + 16
并f(32, 0)
计算为零,所以16
返回。
您也可以这样做,但请注意,这将改变输出的顺序,因为打印输出需要等待返回:
int fun(int a, int b)
{
printf("fun(%d, %d)\n", a, b);
if (b == 0) {
printf("b == 0, returning 0\n");
return 0;
}
if (b % 2 == 0) {
int ret = fun(a+a, b/2);
printf("b is even, returning f(%d, %d) = %d \n", a+a, b/2, ret);
return ret; //fun(a+a, b/2);
}
int ret = fun(a+a, b/2) + a;
printf("b is odd, returning f(%d, %d) + %d = %d \n", a+a, b/2, a, ret);
return ret;
}
输出:
$ ./a.out
fun(4, 4)
fun(8, 2)
fun(16, 1)
fun(32, 0)
b == 0, returning 0
b is odd, returning f(32, 0) + 16 = 16
b is even, returning f(16, 1) = 16
b is even, returning f(8, 2) = 16
16
理解递归的一个好方法是使用笔和纸来了解为什么在这些情况下打印输出的顺序如此不同。但我把它留给你。
推荐阅读
- php - 通过 google facebook 和 linkedIn 或第三方(如 hybridAuth)使用直接 oauth
- multithreading - Goroutines 和 C 线程之间的原子栅栏并发——语义是什么?
- docker - 访问 Microsoft 容器图像数据的 URL
- java - 使用 Apache PropertyUtils 在 protobuf 生成的类中获取嵌套列表对象的属性
- android - 在 SQLite 中连接出 SELECT
- html - 编码 fitbit 表盘 - 组和中心图像
- javascript - .html( ) 内的粗体文本
- python - 从数据 pyspark 中删除控制 - 相当于 PySpark 中的 [[:cntrl:]]
- python - 在python中使用矩形簇进行聚类
- javascript - jQuery.hoverDelay.js 插件未检测到附加元素