我一直试图通过Code :: Blocks:
在我的MinGW上执行这个程序#include <string.h>
#include <math.h>
#include <stdio.h>
#define N 100
int p[N];
int pr[N];
int cnt;
void sieve()
{
int i,j;
for(i=0;i<N;i++) pr[i]=1;
pr[0]=pr[1]=0;
for(i=2;i<N;i++)
if(pr[i])
{
p[cnt]=i; cnt++;
for(j=i+i;j<=N;j+=i) pr[j]=0;
}
}
int main(){
sieve();
int i;
for(i=0;i<cnt;i++)
printf("%d ",p[i]);
puts("");
printf("Total number of prime numbers : %d",cnt);
return 0;
}
在我的系统上,输出为:
7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
素数总数:22
这完全是疯了,因为我完全确定算法的实现。
所以我决定在Ideone中尝试它,它提供正确的输出。任何人都可以指出原因吗?
我将其更改为N,但输出不会改变。
答案 0 :(得分:6)
不,它实际上被称为Debanjan错误:-)看看 this :
#define N 100
int p[N / 64];
在我看来,您只允许足够的空间在p
数组中存储一个素数。这意味着,为p[X]
写X > 0
可能会覆盖其他值。
这是可怕的未定义行为,这意味着任何都可能发生(包括它在Ideone情况下的工作)。
只需使用:
int p[N];
声明数组。我很确定不会有超过100个小于或等于100的素数: - )
答案 1 :(得分:5)
您的代码中有两个重要的错误。
一个是你的p数组太小了,所以你要写下它的结尾。这是未定义的行为,但在您使用它的平台上会覆盖pr数组的开头。这对输出没有影响,因为您要覆盖的位置在您在筛子中测试的位置之前。
另一个是你还在写pr
数组的末尾:
for(j=i+i;j<=N;j+=i) pr[j]=0;
此循环将pr[N]
设置为零,这不在pr
的末尾。在MinGW中,这是cnt
存储的位置,因此每次i
除N
时,cnt
都会设置为零。当N
为100时,i==2
和i==5
会发生这种情况,因此您的结果会在五次之前丢失素数。 IdeOne似乎将cnt
放在与pr
相关的其他位置,因此它不会被覆盖。这就是为什么你用不同的编译器得到不同的输出。
将数组p的大小更改为N,或者仅对筛选和输出使用一个数组,并将第18行中的<=
更改为<
,这样就不会注销结束它
int p[N];
int *pr = p; // reuse the array
答案 2 :(得分:2)
您的数组p
只有一个元素,因为您使用整数除法100/64
声明它。
将其更改为
int p[N];
或具有至少25个元素的东西。
答案 3 :(得分:1)
没有。我不相信在这种情况下会有一个MinGW错误。
您的应用程序中存在错误。正如之前提到的那样, p 数组只有只有1个元素。 (处理整数值时,100/64 = 1)。
这意味着当您在 p [1]或p [2]或p [3] (超出数组范围)之后访问时,您将在 p <之后实际访问区域内存/ em>这是 pr 数组。
使用Ideone我相信阵列的内存区域可能距离更远,而不是像MinGW那样一个接一个(这只是一个假设)。
答案 4 :(得分:0)
数组p
太小,您将超出它并写入pr
。
变化:
int p[N / 64];
为:
int p[N / 2];
Foonote:永远不会因为你看到一个你无法立即解释的问题而假设编译器错误。 99.999%的时间它你的错误 - 你还没有找到它。
答案 5 :(得分:0)
100/64是1.所以p只有一个元素 - p [0]。当您访问p [1],p [2]等时,您开始覆盖pr数组中的元素。这会产生错误的结果。
这是你程序中的一个错误,而不是一个mingw bug。