我最近开始学习c,这是我的第一种编码语言。我正在尝试解决Project Euler中的问题3,并且我写了这样做。此代码旨在确定最大的素数因子600851475143, 但相反,我得到了一个我不明白的奇怪的回报价值。谁知道为什么?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 1, a = 0, prime = 0;
for(i = 1; i < 600851475143; i += 2) {
for(a = 0; a <= i / 2; a++) {
if(i % a == 0) {
break;
}
if(a = i / 2) {
if(600851475143 % i == 0) {
prime = i;
}
}
}
}
printf("%d\n", prime );
return 0;
}
答案 0 :(得分:3)
除以0(或尝试for(a = 0; a <= i / 2; a++) {
// v---- a is zero!
if(i % a == 0) {
)。这是未定义的行为(UB)并且可以解释-1的返回。使用UB - 任何都可能发生。
在修复之前,其余代码并不重要。
// for(a = 0; a <= i / 2; a++) {
for(a = 2; a <= i / 2; a++) {
代码可能应该从2开始。
i / 2
不是以 v-------------------v Same a <= sqrt(600851475143) without FP or overflow
for(a = 2; a <= 600851475143 / a; a++) {
结束,而是以√600851475143结束,而是很多。
if(a = i / 2)
其他问题也存在。 int
见@Tom Karzes
i < 600851475143
可能在600851475143范围内,因此warning: comparison is always true due to limited range of data type [-Wtype-limits]
始终为真。常见的编译器警告将发出此警告。务必完全启用警告以节省时间。 @iBug
int main(void) {
wide_enough_type n = 600851475143;
wide_enough_type factor = 1;
try each i starting at 2 and until i*i <= n
repeat as long as n divides into i with no remainder
make n smaller by diving it by i
save i as factor
save the larger of (n, factor) as factor
printf("Greatest factor: %some_type_specifier\n", factor);
}
伪代码解决方案
{{1}}
答案 1 :(得分:1)
您的问题称为溢出。由于可用内存有限,所有数据类型的范围都有限。平均现代计算机上的int
通常高达2,147,483,647(警告:我通常说) - 实际上事情有点复杂。无论如何,你的上限超过了这个。
当int
(或有符号整数数据类型)溢出时,由于某些与表示相关的问题,它会变为负数。有关原因的更多详细信息,请查看两个补码表示。
要修复它,请使用范围更广的数据类型。 long long
上升到9,223,372,036,854,775,807,这似乎适合您的需要。
请注意,整数文字也需要标记为long long
,否则它们也会溢出:
for(i = 1; i < 600851475143LL; i += 2)
如果你需要的整数值大于long long
所支持的范围(虽然现在看起来并非如此),你运气不好:你需要找一些聪明的人处理它的方法。
要查找的其他内容是,当我运行代码时,我得到除以0.我不知道这是否与溢出有关。