为什么这个阶乘计算不正确?

时间:2017-10-07 05:14:25

标签: c factorial

我正在尝试学习一些C编程,并且为了测试我的基本技能,我正在制作一个计算阶乘的简单程序。但是,不是给5的阶乘给出120的正确答案,而是给出-1899959296。怎么了?这是我的代码:

#include <stdio.h>

int factorial(int x)
{
    int i;
    for(i=1; i < x; i++)
        x *= i;
    return x;
}

int main() 
{ 
    int a = 5, b;
    b = factorial(a);
    printf("The factorial of %d is %d \n", a, b);
    return 0;
}

提前致谢!

4 个答案:

答案 0 :(得分:3)

    int factorial(int x)
    {
        int i;
        int count =x;
        for(i=1; i < count ; i++)
            x *= i;
        return x;
    }

像这样修改。你的问题是循环计数..由于x的值正在改变,循环可能变为无限..

答案 1 :(得分:3)

您的问题是函数factorial()不断修改x。对于最初为x或更多3的任何xfact(3)将继续增加,因此循环将继续运行。

考虑您是否致电x = 3

使用i = 1调用该函数。使用x的循环的第一次迭代将1乘以x。因此3仍然具有i的值。 i 2将增加到3,小于x,因此下一次迭代开始。

循环的第二次迭代将2乘以6,得到i的结果。 3递增到6,小于x,因此下一次迭代开始。

第三次迭代会将3乘以18,得到i的结果。 4递增到18,小于i < x,因此下一次迭代开始。

注意上面的模式.....结束条件是ix在每次迭代中递增。 i乘以x。这意味着i的增长速度明显快于i < x ....这意味着x始终为真。

差不多......最终逻辑崩溃了。

最终i会溢出 - 将其乘以int的结果将产生超出int中可存储的结果的结果。溢出3的结果是未定义的.....在那一点上可能发生任何事情。

将上述说明与要求计算jest.mock()的阶乘的情况进行比较。你会做类似的步骤吗?可能不是。

答案 2 :(得分:1)

C)您使用x作为for循环i < x

的上限

B)你也在每个循环x *= i上几乎以指数方式增加x,你的循环不起作用。

你可能已经注意到你得到了一个负数。循环退出的原因是你选择输入x作为32位有符号整数(默认为int) - 处理器以二进制方式工作:所以一旦你比实际可能只有32更高比特,它仍然试图做数学,但它会丢失数据并循环回到负数。因此,一旦x循环并变为负数,则i > x并且循环退出。

此处:http://tpcg.io/8sX5ls

答案 3 :(得分:1)

错误在for,数字的阶乘是 n * n-1 * ... * n-(n-1),所以为了解决这个问题,只需在x - 1中开始索引并递减直到它变为1,抱歉我的英语不好,我希望你能理解我说的话。

这是答案:

for ( i = x - 1; i > 1; --i )
        x *= i;

只是为了解释为什么是负数,首先我们必须了解for所宣告的内容。

for(i=1; i < x; i++)
        x *= i;

我们可以看到它在循环中继续的条件为i < x,但在其中x的值为x * ix * = i or x = x * i),因此x没有常数值并且总是在增加,i以小于x的速度增加,因为i总是添加到1({{1} }}),导致i ++, i + = 1 or i = i + 1无法访问,然后x将处于无限循环中。

但是每个类型都有它的范围,而for是4个字节,因此是32位,会发生的事情是int超过这个范围时有着名的整数溢出,这就是为什么其值为负,则x的条件变为false,然后for停止。

我们必须记住,数字在二进制形式的内存中表示,最后一个二进制数表示数字是正数还是负数,0表示正数,1表示负数,当整数溢出发生时,最后一个数字发生变化到1,使它如此消极。

为了更好地理解这一点,有些链接可以提供帮助:

https://en.wikipedia.org/wiki/Two%27s_complement

https://en.wikipedia.org/wiki/Integer_overflow