为什么这个阶乘计算不正确?
Why doesn't this factorial compute correctly?
我正在尝试学习一些 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;
}
提前致谢!
int factorial(int x)
{
int i;
int count =x;
for(i=1; i < count ; i++)
x *= i;
return x;
}
这样修改。你的问题是循环计数。由于 x 的值正在改变循环可能会变成无限的..
您的问题是函数 factorial()
不断修改 x
。对于任何初始为 3
或更多的 x
,x
将不断增加,因此循环将保持 运行。
如果你打电话给fact(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
。 i
在每次迭代中递增。 x
乘以 i
。这意味着 x
比 i
增长得快得多......这意味着 i < x
总是正确的。
好吧几乎.....最终逻辑崩溃了。
最终 x
会溢出 - 将其乘以 i
的结果将超过 int
中可以存储的结果。 int
溢出的结果是未定义的..... 那时任何事情都可能发生。
比较上面的描述和如果被要求计算 3
的阶乘你会怎么做。你会做类似的步骤吗?可能不是。
C) 您正在使用 x 作为 for 循环的上限 i < x
B) 你还在每个循环中几乎以指数方式增加 x x *= i
,你的循环将不起作用。
您可能已经注意到您得到了一个负数。循环完全退出的原因是您选择将 x 键入为 32 位带符号整数(默认值 int
)- 处理器以二进制工作:因此一旦您超出实际可能的 32位,它仍然尝试进行数学运算,但它丢失了数据并循环回到负数。因此,一旦 x 返回并变为负值,然后 i > x
并且循环退出。
错误在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 * i
的值(x * = i or x = x * i
), 所以 x
没有常数值并且一直在增加, i
以比 x
小的速度增加,因为 i
总是加 1 (i ++, i + = 1 or i = i + 1
),导致x
不可达,那么for
就会死循环。
但是每个类型都有它的范围,int
是 4 个字节,因此是 32 位,会发生什么时候 x
超出这个范围就会出现著名的整数溢出,这这就是为什么它的值为负,然后 for
的条件变为假,然后 for
停止。
我们要记住,一个数在内存中是以二进制形式表示的,最后一个二进制数就是表示这个数是正数还是负数,0为正数,1为负数,最后一个整数溢出时number 变为 1 ,使其变为负值。
为了更好地理解这一点,这里有一些可以提供帮助的链接:
我正在尝试学习一些 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;
}
提前致谢!
int factorial(int x)
{
int i;
int count =x;
for(i=1; i < count ; i++)
x *= i;
return x;
}
这样修改。你的问题是循环计数。由于 x 的值正在改变循环可能会变成无限的..
您的问题是函数 factorial()
不断修改 x
。对于任何初始为 3
或更多的 x
,x
将不断增加,因此循环将保持 运行。
如果你打电话给fact(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
。 i
在每次迭代中递增。 x
乘以 i
。这意味着 x
比 i
增长得快得多......这意味着 i < x
总是正确的。
好吧几乎.....最终逻辑崩溃了。
最终 x
会溢出 - 将其乘以 i
的结果将超过 int
中可以存储的结果。 int
溢出的结果是未定义的..... 那时任何事情都可能发生。
比较上面的描述和如果被要求计算 3
的阶乘你会怎么做。你会做类似的步骤吗?可能不是。
C) 您正在使用 x 作为 for 循环的上限 i < x
B) 你还在每个循环中几乎以指数方式增加 x x *= i
,你的循环将不起作用。
您可能已经注意到您得到了一个负数。循环完全退出的原因是您选择将 x 键入为 32 位带符号整数(默认值 int
)- 处理器以二进制工作:因此一旦您超出实际可能的 32位,它仍然尝试进行数学运算,但它丢失了数据并循环回到负数。因此,一旦 x 返回并变为负值,然后 i > x
并且循环退出。
错误在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 * i
的值(x * = i or x = x * i
), 所以 x
没有常数值并且一直在增加, i
以比 x
小的速度增加,因为 i
总是加 1 (i ++, i + = 1 or i = i + 1
),导致x
不可达,那么for
就会死循环。
但是每个类型都有它的范围,int
是 4 个字节,因此是 32 位,会发生什么时候 x
超出这个范围就会出现著名的整数溢出,这这就是为什么它的值为负,然后 for
的条件变为假,然后 for
停止。
我们要记住,一个数在内存中是以二进制形式表示的,最后一个二进制数就是表示这个数是正数还是负数,0为正数,1为负数,最后一个整数溢出时number 变为 1 ,使其变为负值。
为了更好地理解这一点,这里有一些可以提供帮助的链接: