gpt4 book ai didi

c - 用于查找数字阶乘的递归函数

转载 作者:行者123 更新时间:2023-12-04 12:19:16 25 4
gpt4 key购买 nike

我得到 24 的输出,这是 4 的阶乘,但我应该得到 5 阶乘的输出,即 120

#include <stdio.h>
int factorial(int number){
if(number==1){
return number;
}
return number*factorial(--number);
}
int main(){
int a=factorial(5);
printf("%d",a);
}

最佳答案

您的程序存在未定义的行为。
第一次拨打 factorial(5) ,你有

return number * factorial(--number);
你想象这将计算
       5      * factorial(4);
但这并不能保证!
如果编译器以不同的顺序查看它会怎样?
如果首先在右侧工作会怎样?
如果它首先执行等效于:
temporary_result = factorial(--number);
然后做乘法:
return number * temporary_result;
如果编译器按该顺序执行,则 temporary_result将是 factorial(4) ,它会返回 4 倍,不会是 5! .基本上,如果编译器按照这个顺序来做——它可能会! -- 然后 number “过早”递减。
您可能没有想到编译器可以以这种方式做事。
您可能已经想象到表达式总是“从左到右解析”。
但这些想象是不正确的。
(另见 this answer 有关评估顺序的更多讨论。)
我说表达式会导致“未定义行为”,这个表达式就是一个经典的例子。使这个表达式未定义的原因是它内部发生的事情有点太多了。
表达的问题
return number * factorial(--number);
是变量 number在其中使用了它的值,以及相同的变量 number也在里面修改。这种模式基本上是毒药。
让我们标记这两个位置 number出现,以便我们可以非常清楚地谈论它们:
return number * factorial(--number);
/* A */ /* B */
在点 A 我们取变量 number 的值.
在 B 点,我们修改变量 number 的值.
但问题是,在 A 点,我们得到的是 number 的“旧”值还是"new"值? ?
我们是在 B 点修改它之前还是之后得到它?
正如我已经说过的,答案是:我们不知道。 C 中没有规则可以告诉我们。
同样,您可能认为存在关于从左到右求值的规则,但实际上并没有。因为没有规则说明应该如何解析这样的表达式,所以编译器可以做任何它想做的事情。它可以以“正确”的方式或“错误”的方式解析它,或者它可以做一些更奇怪和意想不到的事情。 (而且,实际上,首先没有“正确”或“错误”的方式来解析这样的未定义表达式。)
解决这个问题的方法是:不要那样做!
不要编写同时使用和修改一个变量(如 number )的表达式。
在这种情况下,正如您已经发现的那样,有一个简单的修复方法:
return number * factorial(number - 1);
现在,我们实际上并不是要修改变量 number 的值。 (正如表达式 --number 所做的那样),在将较小的值传递给递归调用之前,我们只是从它减去 1。
所以现在,我们没有违反规则,我们没有使用和修改 number在同一个表达中。
我们只是两次使用它的值,这很好。
有关此类表达式中未定义行为的更多(更多!),请参阅 Why are these constructs using pre and post-increment undefined behavior?

关于c - 用于查找数字阶乘的递归函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68024823/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com