我不明白为什么我在这段代码中出现运行时错误。问题是每个> = 6的数字都可以表示为两个质数之和。我的代码是......预先感谢,问题链接是http://poj.org/problem?id=2262
#include "stdio.h"
#include "stdlib.h"
#define N 1000000
int main()
{
long int i,j,k;
long int *cp = malloc(1000000*sizeof(long int));
long int *isprime = malloc(1000000*sizeof(long int));
//long int *isprime;
long int num,flag;
//isprime = malloc(2*sizeof(long int));
for(i=0;i<N;i++)
{
isprime[i]=1;
}
j=0;
for(i=2;i<N;i++)
{
if(isprime[i])
{
cp[j] = i;
j++;
for(k=i*i;k<N;k+=i)
{
isprime[k] = 0;
}
}
}
//for(i=0;i<j;i++)
//{
// printf("%d ",cp[i]);
//}
//printf("\n");
while(1)
{
scanf("%ld",&num);
if(num==0) break;
flag = 0;
for(i=0;i<j&&num>cp[i];i++)
{
//printf("%d ",cp[i]);
if(isprime[num-cp[i]])
{
printf("%ld = %ld + %ld\n",num,cp[i],num-cp[i]);
flag = 1;
break;
}
}
if(flag==0)
{
printf("Goldbach's conjecture is wrong.\n");
}
}
free(cp);
free(isprime);
return 0;
}
我马上想到两种可能性。首先是,如果使用的任何测试工具均未提供任何输入,则用户输入可能会失败。在不了解有关线束的更多细节的情况下,这充其量只是个猜测。
您可以通过对值进行硬编码而不是从标准输入中接受一个值来进行检查。
另一种可能性是完成了相当大的内存分配。可能是您处在一个受限的环境中,不允许这样做。
一个简单的测试就是删除N
(并顺便使用它的值,而不是1000000
在malloc
调用中使用多个硬编码的数字)的值。更好的方法是检查from的返回值malloc
以确保它不是NULL。无论如何应该这样做。
而且,除此之外,您可能还需要检查您的Eratosthenes Sieve代码。应标明非黄金的黄金的第一个项目i
是i + i
不是i * i
因为你。我认为应该是:
for (k = i + i; k < N; k += i)
该数学算法,因为任何倍数实际上是没关系N
小于N * N
将已经被标记为非主要凭借的事实,这是先前检查的质数之一的倍数。
您的问题在于整数溢出。在点在哪里N
成为46_349
,N * N
是2_148_229_801
它,如果你有一个32位二进制补码整数(最大值2_147_483_647
),将环绕到-2_146_737_495
。
发生这种情况时,循环将继续进行,因为该负数仍小于您的限制,但是,将其用作数组索引是不明智的:-)
它起作用的原因i + i
是因为您的限制很短,INT_MAX / 2
所以那里没有溢出发生。
如果您想确保在起床时不会出现问题INT_MAX / 2
,可以使用以下方法:
for (k = i + i; (k < N) && (k > i); k += i)
k
如果您的包裹遵循“正常”行为,那么额外的检查应该捕获绕回事件-从技术上讲,我认为包裹是未定义的行为,但是由于两者的补码性质,大多数实现只是将两个肯定的包裹回为否定。请注意,这实际上是不可移植的,但是实际上这意味着它只能在99.999%的机器上运行:-)
但是,如果您是便携性的坚持者,那么首先就有更好的方法来防止溢出。我在这里不做介绍,而是要说它们涉及从被求和的一项中减去一个项MAX_INT
,并将其与另一个被求和的项进行比较。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句