我正在尝试在C中实现eratosthenes的筛子。该代码适用于小输入值,但是一旦输入超出某个范围,就会抛出运行时错误。这是SPOJ基础经典部分的第二个问题。这是什么错误?
#include<stdio.h>
#include<math.h>
int prime(unsigned long int, unsigned long int);
int main()
{
int nitem;
unsigned long int sn,fn;
scanf("%d", &nitem);
while(nitem)
{
scanf("%lu", &fn);
//printf("%d",fn);
scanf("%lu", &sn);
prime(fn, sn);
nitem--;
}
return 0;
}
int prime(unsigned long int fn, unsigned long int sn)
{
unsigned long int prim[100000];
int i,j,k;
for(i = 0; i < 100000; i++)
{
prim[i] = 1;
}
prim[0] = 0;
prim[1] = 0;
//printf("%d", sn);
//printf("%d", k);
//printf("%d", (k <= sn));
for(k = 2; k <= sqrt(sn); k++)
{
// printf("alksnc%5d", k);
if(prim[k] == 1)
{
for(j = 2; (k * j) <= sn; j++)
{
//printf("%d", prim[k]);
prim[k * j] = 0;
}
}
}
for(int i = 0; i <= sn; i++)
{
if(prim[i] !=0 && i >= fn)
{
printf("%lu\n", i);
}
}
printf("\n");
return;
}
输入:
1
100000 100345
输出:
run time error
输入:
1
3 5
输出:
3
5
答案 0 :(得分:0)
我们可以通过仅筛选奇数来更有效地使用内存(2x),因为您处理的所有偶数都会浪费时间和空间。解决这个问题比较困难但给我们提供了类似的东西:
#include <math.h>
#include <libc.h>
#define MAX_ODD_PRIMES 1048576
void prime(unsigned long fn, unsigned long sn)
{
unsigned char primes[MAX_ODD_PRIMES];
for (unsigned long i = 0; i < MAX_ODD_PRIMES; i++)
{
primes[i] = TRUE;
}
primes[0] = 0; // preset first odd, '1'
for (unsigned long k = 3; k <= sqrt(sn) + 1; k += 2)
{
if (primes[k / 2])
{
for (unsigned long j = 3; (k * j) <= sn; j += 2)
{
primes[k * j / 2] = FALSE;
}
}
}
if (fn <= 2)
{
printf("2\n");
fn = 3;
}
for (unsigned long i = fn / 2; i * 2 + 1 <= sn; i++)
{
if (primes[i])
{
printf("%lu\n", i * 2 + 1);
}
}
}
示例强>
> ./a.out
1 1999900 2000000
1999957
1999969
1999979
1999993
>
答案 1 :(得分:0)
1)阵列范围错误。
通过更改代码
for (j = 2; (k * j) <= sn; j++) {
if (k * j >= 100000) {
printf("Out of range %d %d\n", k, j);
exit(1);
}
prim[k * j] = 0;
}
}
输入2,100000
输出
Out of range 2 50000
通过使用适合任务的数组(VLA),可以避免这种情况。许多其他优化可用。还要考虑malloc()
数组。
void prime(unsigned long int fn, unsigned long int sn) {
unsigned long int prim[sn + 1];
2)int prime()
最终执行return;
,其中return something;
是预期的。建议将功能更改为void prime()
int prime(unsigned long int fn, unsigned long int sn) {
unsigned long int prim[100000];
...
printf("\n");
return;
}