【问题标题】:Recursive loop (C#)递归循环 (C#)
【发布时间】:2011-08-11 20:27:33
【问题描述】:

谁能给我解释一下?我在 C# 中编写了一个函数来计算这样一个数字的阶乘:

public int factorial(int input)
{
    if (input == 0 || input == 1)
        return 1;
else
{
    int temp = 1;
    for (int i = 1; i <= input; i++)
        temp = temp * i;
    return temp;
    }
}

但我发现了一些 C++ 代码(我真的不知道任何 C++ 顺便说一句),它使用递归循环找到阶乘:

int factorial(int number) {
 int temp;
 if(number <= 1) return 1;
 temp = number * factorial(number - 1);
 return temp;
}

有人可以向我解释它是如何工作的吗?谢谢。

【问题讨论】:

  • 您实际上可以将代码复制到您的 C# 程序中,它应该可以工作。基本上它是一个递归函数/方法。
  • 它是如何工作的?尝试手动模拟它,例如对于数字 = 5,你会很容易理解它;)
  • LLS:问题是,我不明白什么是递归函数。 :\ 主要部分是令人困惑的 C++ 代码中的第 4 行。 @digEmAll:我试过了,但我仍然对第 4 行感到困惑。 :(
  • 从逻辑上而不是编程上考虑它。它的说法取前一个阶乘(它的相同函数无关紧要,它恰好是)并将它乘以 n。
  • @david:我明白了。我只是想告诉你,你根本不需要知道任何关于 C++ 的知识。而且我相信别人会给你很好的解释。

标签: c# c++ loops recursion factorial


【解决方案1】:

递归函数是从同一个函数调用的函数

例如:

  Test()
    {
      i++;
      Test();
      cout<<i;
    }

看看它会一次又一次调用函数的代码

递归问题,它将无限工作,因此希望通过特定条件停止它

现在看起来上面代码的一些变化

int i=0; 
Test()
        {
         if(i==10) return;
         i++;
         Test();
         cout<<i;
        }

输出10次,打印10次,这里cout&lt;&lt;i;这行会在return后执行

【讨论】:

    【解决方案2】:

    递归函数是在其主体中调用自身的函数。对于它是有界的,并最终返回一个值,必须发生两件事:

    1. 它必须有一个基本情况,它不会再次调用自己,返回一个已知值。此基本情况停止递归。对于阶乘函数,当输入为0时,该值为1。

    2. 它的递归应用程序必须收敛到基本情况。对于阶乘,递归应用程序调用输入减去 1 的函数,最终将收敛到基本情况。

    查看此函数的一种更简单的方法是(仅对正输入有效):

    int factorial(int input) {
      return input == 0 ? 1 : input * factorial(input - 1);
    }
    

    【讨论】:

      【解决方案3】:

      在语法上,C++ 代码与用 C# 编写的相同代码相同。不要让语言差异让您措手不及!考虑到变量是在函数顶部声明的,它对我来说实际上看起来像 C;这在 C++ 或 C# 中都不是绝对必要的。我更喜欢在第一次使用变量时声明它们,将声明和初始化组合在一个语句中,但这只是一种风格偏好,不会改变代码的功能。

      我将尝试通过在代码 sn-p 的每一行添加 cmets 来解释这一点:

      // Declare a function named "Factorial" that accepts a single integer parameter,
      // and returns an integer value.
      int Factorial(int number)
      {
          // Declare a temporary variable of type integer
          int temp;
      
          // This is a guard clause that returns from the function immediately
          // if the value of the argument is less than or equal to 1.
          // In that case, it simply returns a value of 1.
          // (This is important to prevent the function from recursively calling itself
          // forever, producing an infinite loop!)
          if(number <= 1) return 1;
      
          // Set the value of the temp variable equal to the value of the argument
          // multiplied by a recursive call to the Factorial function
          temp = number * Factorial(number - 1);
      
          // Return the value of the temporary variable
         return temp;
      }
      

      Recursive calls 仅表示该函数从同一函数中调用自身。这是可行的,因为 n 的阶乘等同于以下语句:

      n! = n * (n-1)! 
      

      了解代码如何工作的一个很好的方法是将其添加到测试项目中,然后使用调试器单步执行代码。 Visual Studio 在 C# 应用程序中对此提供了非常丰富的支持。您可以观察函数如何递归调用自身,观察每一行按顺序执行,甚至可以看到变量的值随着对它们执行操作而发生变化。

      【讨论】:

      • 这里有很多很棒的回应,但你的解释很好。非常感谢! :) 也是的,我会摆弄调试器,看看它是如何工作的。
      【解决方案4】:

      让我们逐行分析:

      if(number <= 1) return 1;
      temp = number * factorial(number - 1);
      return temp;
      

      第 1 行:如果数字小于或等于 0,则返回 1。这表示 0! = 1 和 1! = 1

      第 2 + 3 行:否则我们返回 number * factorial(number - 1)。让我们看一下5!(这里为了简洁,我使用n! 作为factorial(n) 的同义词)

      5!
      5 * 4!
      5 * 4 * 3!
      5 * 4 * 3 * 2!
      5 * 4 * 3 * 2 * 1!
      5 * 4 * 3 * 3 * 1 // Here we don't have to expand 1! in the same way because of the condition
      

      所以整个事情展开了。它只是使用

      的属性

      n! = n * (n - 1) * ... * 2 * 1 = n * (n - 1)!

      警告:与迭代(或尾递归优化)版本相比,递归代码将一如既往地遭受堆栈溢出和内存使用量增加,因此使用风险自负。

      【讨论】:

        【解决方案5】:

        嗯,它使用factorial(n) 是n * factorial(n - 1) 的事实,基本情况为n = 1。

        例如:

        factorial(5) = 5 * factorial(4)
                     = 5 * 4 * factorial(3)
                     = 5 * 4 * 3 * factorial(2)
                     = 5 * 4 * 3 * 2 * factorial(1)
                     = 5 * 4 * 3 * 2 * 1
        

        实现只是使用这个递归定义。

        【讨论】:

        • 技术上数学上n = 0应该是基本情况,n = 1应该取决于0! = 1这一事实
        猜你喜欢
        • 2014-09-14
        • 1970-01-01
        • 2021-03-20
        • 2018-06-27
        • 2017-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-06
        相关资源
        最近更新 更多