RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 899651
Accepted
Альберт
Альберт
Asked:2020-10-30 06:24:02 +0000 UTC2020-10-30 06:24:02 +0000 UTC 2020-10-30 06:24:02 +0000 UTC

C#。这段代码是如何工作的(关于“return”关键字和递归)?

  • 772
static int Factorial(int n)
{
    if (n == 0)
        return 1;
    else
        return n * Factorial(--n);
}

当然,代码本身实现了它的预期目的,我需要了解它的工作逻辑。看来我了解递归(和复杂递归)的工作和“返回”的工作,但是这个例子中的一些事情并不是那么简单。具体来说,我想知道为什么没有终止“if”的第一个“return”和它返回的数字,这种计算是不可能的?我还在“VS”中“单步执行”了这段代码,目前还不清楚这个阶乘是如何计算的?因为如果你记下计算的值,那么这些是以下表达式:

5 * 4 = 20
4 * 3 = 12
3 * 2 = 6
2 * 1 = 2
1 * 0 = 0

<- 这些表达式是在代码单步执行时由“VS”显示给我的(当然,“VS”并没有以我在这里编写它们的形式显示给我),即第一个因素是我们的“n”第二个因素是 - Factorial(--n),因此,产品是这些因素的产品。我问,有了这样的产品和因子,如何正确计算阶乘?是的,我知道这些问题是由于对整个经济的逻辑(递归、“返回”关键字等)了解不足而引起的 D,因此,事实上,我问了这个问题。我希望我已经把问题说清楚了。)

c#
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. tym32167
    2020-10-30T07:14:28Z2020-10-30T07:14:28Z

    此代码递归地计算阶乘如下:

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

    其中括号是单独的递归级别

    • 3
  2. Sergey Rufanov
    2020-10-30T07:15:01Z2020-10-30T07:15:01Z

    这只是循环退出的一个条件(任何递归都只是一个奇怪的循环——现代编译器中的大多数优化器会立即将它们转换为常规循环),加上等于 0 到 1(因为 1*<any number> = <any number> ) - 如果我们没有将 0 等同于 1,那么最后我们会将所有内容乘以 0 并得到 .. 0

    对于您示例中的数字“5”,不是计算您上面写的内容,而是:

    5 * 4 * 3 * 2 * 1 * 1 = 120
    

    在这里,在第一个条件返回 1 期间,我们不调用 Factorial 函数——在这一步,循环被中断。

    如果没有递归,那么相同的函数将如下所示:

    static int Factorial(int n)
    {
        int result = 1;
    
        for (int i = 1; i <= n; i++)
            result *= i;
    
        // result *= 1; - то самое лишнее  умножение на 1. без рекурсии оно нам не нужно
    
        return result;
    }
    
    • 3
  3. Best Answer
    Alexander Petrov
    2020-10-30T14:00:03Z2020-10-30T14:00:03Z

    当调用 Factorial(5) 时,会创建一个堆栈帧。此堆栈存储 n 的值,等于 5。
    有一个与零的比较。由于它不相等,因此有一个转移到 else 分支。
    乘法尚不可能,稍后将完成。
    阶乘被调用,n 的值减一。那是阶乘(4)。
    保存值 5 的堆栈继续存在。

    一切都以同样的方式发生:创建一个新的堆栈帧,它存储 n 的值,等于 4。
    又是一个分支。乘法仍然是不可能的。
    对 Factorial(3) 的新调用。
    保存值 4 的堆栈继续存在。

    然后调用 Factorial(2)。然后是阶乘(1)。堆栈继续存在。

    最后,调用 Factorial(0)。
    同样,n 的值存储在堆栈中。
    在这里,if 分支最终被执行。将一个返回到下一个级别。
    当前堆栈为零的堆栈被销毁。

    这是最终完成乘法的地方:1 * 1。结果在上面返回。
    持有 1 的堆栈被销毁。

    这一直到顶部:取返回值,乘以存储在当前堆栈帧中的值,然后向上推。
    当前堆栈被销毁。

    当执行到达值为 5 的最顶层堆栈时,也会发生乘法运算并释放堆栈的内存。结果值返回给调用函数。

    • 3

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5