【问题标题】:c recursion program problemc递归程序问题
【发布时间】:2011-06-03 07:26:57
【问题描述】:

我是递归概念的新手。我想编写一个递归函数,它以浮点数和整数作为参数,并以浮点值保持不变而整数值变化的方式递归调用它

我写了以下代码:

#include <stdio.h>

float sum(float f, int k)
{
    static float c;
    c = f - k;
    c = sum(f, k - 1);
    return c;
}

int main()
{
    float f, g = 10.00;
    int i = 5;
    f = sum(g, i);
    printf("the sum of integer and float = %f", f);
}

当我编译它时它没有显示错误,但是当我运行程序时它显示一个分段错误。

我的问题如下:

  1. 代码有什么问题?
  2. 为什么显示分段错误?
  3. 如何在具有多个参数的函数中使用递归?

请用一些有两个参数的递归函数的例子来解释一下。

【问题讨论】:

  • 这条语句c = sum(f, k - 1);应该是c += sum(f, k - 1);。如果涉及逻辑的话。
  • 无终止条件

标签: c++ c segmentation-fault


【解决方案1】:

代码是错误的,因为它永远无法结束(我认为它会因 stackoverflow 错误而失败)。

对于递归,你需要两件事

  1. 基本案例
  2. 向基本情况移动的递归情况

看起来你只有第二个。我怀疑当 k 为零时 sum 应该返回。希望这样的事情有意义:

 float sum(float f, int k) {
     if (k <= 0) {
         // The base case
         return f;
     } else {
         // The recursive case.  This does one step of the work
         // and moves towards the base case
         return 1 + sum(f, k - 1);
     }
 }

【讨论】:

  • 最好使用尾递归,这样栈的大小就保持不变。
  • 是的,如果您的语言支持尾递归,那么我同意。为了解释事情,我认为这是在得到递归之后的讨论。
【解决方案2】:

您的递归没有基本(非递归)终止案例。

对sum 的每次调用都会对其自身进行递归调用,这会一直持续到您的堆栈溢出,从而导致段错误。

【讨论】:

    【解决方案3】:

    递归永远不会停止,最终你会用完堆栈。您需要决定何时停止递归。例如,如果k 等于 0,您不会再次调用sum,而是使用return 退出。

    float sum(float f ,int k)
    {
        static float c;
        if (k > 0)
        {
            c=f-k; /// <<< why is this here? you ignore the value and overwrite it in the next step.
            c=sum(f,k-1);
        }
        return c;
    }
    

    当然还有其他问题:将c设为静态可能会影响计算的正确性,而且我标记的地方看起来很可疑,因为您丢失了值并用随后的调用覆盖它sum.

    【讨论】:

      【解决方案4】:

      这个怎么样?

      #include <stdio.h>
      float sum(float f, int k, float c) {
          if (k == 0)
              return c;
          sum(f, k - 1, f - k);
      }
      

      【讨论】:

        【解决方案5】:

        我看到的第一件事是你的递归没有终止。它会永远持续下去。也许你想要:

        float sum(float f ,int k)
        {
            static float c;
        
            c=f-k;
            if (k != 0)
                c=sum(f,k-1);
            return c;
        }
        

        所以当 k 为零时递归停止。你有一个堆栈溢出。

        【讨论】:

          【解决方案6】:

          当你进行递归时,你需要一个状态来结束它。

          所以你的代码有变化:

          #include <stdio.h>
          
          float sum(float f, int k)
          {
              if(k == 0) return f;
              return 1 + sum(f,k-1);
          }
          
          int main()
          {
              float f, g = 10.00;
              int i = 5;
              f = sum(g, i);
              printf("the sum of integer and float = %f", f);
          }
          

          使用该代码,以及您的示例 f=10.00 和 i=5

          Call sum(10.0, 5)
          return 1 + sum(10.0, 4)
                     1 + sum(10.0, 3)
                         1 + sum(10.0, 2)
                             1 + sum(10.0, 1)
                                 1 + sum(10.0, 0)
                                     10
                                 1 + 10 = 11
                             1 + 11 = 12
                         1 + 12 = 13
                     1 + 13 = 14
                 1 + 14 = 15
          return 15;
          

          【讨论】:

            【解决方案7】:

            我不明白“sum”函数的用途。它应该添加f和k吗?在这种情况下,没有递归;您应该只添加 f 和 k:return f + k。

            但要尝试回答您的问题:

            1. 没有基本情况。这就是无限递归的原因。每个递归函数都需要一个基本情况,这是它不递归的条件。无论如何,您的函数都会递归;因此它将永远递归。
            2. 当递归段错误时,通常是由于堆栈溢出(没有双关语);这意味着您将永远递归并最终耗尽空间。
            3. 您可以在具有多个参数的函数中使用递归,就像任何其他函数一样。只需使用下一次迭代的新值调用它即可。

            请注意,您通常有一个“恒定”值,在递归期间不会改变。为此,您只需在递归调用中传递不变的值,因此每一步都可以使用相同的值。

            【讨论】:

              猜你喜欢
              • 2012-11-13
              • 2012-03-07
              • 2021-03-22
              • 2020-05-30
              • 2011-01-16
              • 1970-01-01
              • 1970-01-01
              • 2023-04-09
              • 1970-01-01
              相关资源
              最近更新 更多