输入值大于100000时发生运行时错误

时间:2016-06-18 15:44:36

标签: c

我正在尝试在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

2 个答案:

答案 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;
}