【问题标题】:Recursive Fibonacci in C, using fork()C中的递归斐波那契,使用fork()
【发布时间】:2013-09-13 21:50:44
【问题描述】:

首先,我欣然承认这是功课。但是我一直把头撞在墙上,我就是不明白。赋值参数如下:“递归计算指定数。如果print为真,则打印。否则,提供给我的父进程。

注意:解决方案必须是递归的,并且必须为每个调用派生一个新的孩子。每个进程应该只调用一次doFib()。”

这是我第一次使用 fork(),虽然我想我明白了,但我无法理解为什么我没有得到正确答案。这是我的代码,相当简陋:

doFib(int n, int doPrint)
{
    int status;
    int print;
    pid_t pid1;
    pid_t pid2;
    int sum1;
    int sum2;

    if (n < 2)
        exit(n);

    pid1 = fork();

    if (pid1 == 0)
    {
        doFib(n-1, doPrint);
        exit(n-1);
    }

    pid2 = fork();

    if (pid2 == 0)
    {
        doFib(n-2, doPrint);
        exit(n-2);
    }

    while ((pid1 = waitpid(-1,&status, 0)) >0)
    {
        if(WIFEXITED(status))
            sum1 += WEXITSTATUS(status);
    }

    while ((pid2 = waitpid(-1,&status, 0)) >0)
    {
        if(WIFEXITED(status))
            sum2 += WEXITSTATUS(status);
    }

    print = sum1 + sum2;

    if(doPrint)
        printf("%d\n", print);
    else
        exit(0);
}

斐波那契是我学习的第一个递归示例之一,我在基本层面上理解它。但是,当我运行我的程序时,将 10 作为给定参数(尽管任何参数都会产生不正确的结果),我得到一个以 -1861761537 结尾的垃圾流(有很多这样的负数),17。任何更改我make 会产生不同的垃圾值,但最终仍为 17。

我相信问题在于我使用了 waitpid,但我不知道它会是什么。我是否正确假设这是我的错误的根源?我搜索了教科书、手册页、互联网等,但我不知道我能解决什么问题。任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 你能正确缩进你的代码吗?
  • 不鼓励在生产代码中使用递归。参见例如 NASA 指导方针:lars-lab.jpl.nasa.gov/JPL_Coding_Standard_C.pdf
  • 很高兴他们正在计算 finincci 数字 递归;因为教导学生 O(2^n) 代码是可以接受的,这肯定会让他们在以后的生活中取得成功。
  • 很抱歉出现缩进问题——我以前从未在 Stack Overflow 上发布过代码。不幸的是,我别无选择。解决方案必须是递归的并且必须使用 fork。这项任务在基础级别上很愚蠢,但我的挫败感源于我没有得到的任何 waitpid 元素。 (除非在我没有看到的递归中有明显的错误。)
  • @awashburn 好吧,O(phi^n),但重点。只要他们学会了记忆的东西,事情应该不会太糟糕。

标签: c recursion


【解决方案1】:

WEXITSTATUS()sum1sum2 赋值时,您使用了+= 赋值而不是= 赋值。因为sum1sum2 从未被初始化,这为你的程序中的垃圾数据创建了一个插入向量。

也正如Zackcomments 中指出的那样, 由于退出状态最大值为255,该代码将无法在Unix 机器上运行值n &gt;= 15

【讨论】:

  • 这在逻辑上是有道理的,但在执行时它给了我 375 的输出。某事运行 FAR 太多次了。
  • @MartyEischeid 是的,我最初的测试导致了似乎是算术溢出...仍然有问题...
  • 好吧,我发现了一个问题:根本没有进入第二个 while 循环。我目前正在测试一些修复程序以确定为什么会这样。
  • 我不知道这是否是实际问题,但您只能可靠地使用 0 到 127 作为退出代码。 (许多但不是所有系统都允许 0 到 255。我从未见过允许更大值的 Unixy 系统。)
  • @Zack 我相信你是对的。我尝试使用这个程序增量计算值。它正确生成了fib(14): 337 == 144 + 233,但未能生成fib(15): 354 != 233 + 337。我认为这是因为,正如您所指出的,337 &gt; 255 不能成为退出状态。还有354 = 233 + 337%256.
【解决方案2】:

我会试一试:

 exit(n-1);

为什么要减少输入作为退出值?如果我正确阅读了代码的意图,则退出值应该是中间结果

附录

:) 因为这是作业,所以我不会给你答案。另外,由于我不知道答案,所以很长时间没有使用 fork()。

相反,将答案视为模式替换:

  1. 第一个模式是普通的递归 Fib 函数,具有同步调用
  2. 第二种模式是从异步派生而不是同步调用中检索结果

编写第一个模式并对其进行测试,然后用第二个模式对其进行转换。至少有两个正确的解决方案。找到两者。

【讨论】:

  • 那么进程的当前“n”是我要退出的值吗?然后递归调用将处理“n-1”和“n-2”的情况。使两个退出语句都读取为“exit(n)”的快速测试产生了类似的垃圾流,该流在 20 结束,至少更接近所需的 55,尽管我可能误读了您的问题。
【解决方案3】:

您需要做的是调试您的程序。我建议先给它一个简单的执行路径,然后看看它做了什么。例如,从 n=1 开始,然后 n=2,然后 n=3。注释掉第二个分叉代码并专注于让第一部分工作。利用 print 语句检查程序中不同点的变量值 - 这将为您提供有关它如何工作的线索。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 2010-12-03
    • 2019-01-21
    • 2014-04-02
    • 2016-07-01
    • 1970-01-01
    相关资源
    最近更新 更多