【问题标题】:error with array size数组大小错误
【发布时间】:2015-10-25 17:32:56
【问题描述】:

我正在尝试制作一个程序,使用 Eratosthenes 的筛子计算不超过整数的素数数量。虽然我的程序对于小数字运行良好(并且快速),但在某个数字(46337)之后,我得到一个“命令由信号 11 终止”错误,我认为这与数组大小有关。我尝试使用 malloc() 但我没有完全正确。大数字(高达 50 亿)我该怎么办?

#include <stdio.h>
#include<stdlib.h>
int main(){
signed long int x,i, j, prime = 0;
scanf("%ld", &x);
int num[x];
for(i=2; i<=x;i++){
  num[i]=1;
}
for(i=2; i<=x;i++){
  if(num[i] == 1){
    for(j=i*i; j<=x; j = j + i){
      num[j] = 0;
    }
    //printf("num[%d]\n", i);
    prime++;
  }
}
 printf("%ld", prime);
 return 0;
}

【问题讨论】:

  • 数组索引从 0 到 size 减一。
  • 'for(i=2; i
  • 哦...我的速度不够快。在检查 for 循环索引之前,我浪费了时间检查 strlen/sizeof(pointer):(
  • @JoachimPileborg 我认为这不是问题,因为它适用于最多 46337 的每个数字
  • 如果您使用单个位而不是整个 int 来存储 0 或 1,大数字将起作用。也许是 std::vector&lt;bool&gt; 的少数几个好的用途之一?

标签: c primes sieve-of-eratosthenes


【解决方案1】:

你的数组

int num[x];

在堆栈上,只能容纳小数组。对于大数组大小,您必须分配内存。您可以使用char 类型来节省内存膨胀,因为您只需要一个状态。

char *num = malloc(x+1);              // allow for indexing by [x]
if(num == NULL) {
    // deal with allocation error
}

//... the sieve code

free(num);

我还建议,您必须使用

检查 i*i 是否没有打破 int 限制
if(num[i] == 1){
    if (x / i >= i){                  // make sure i*i won't break
        for(j=i*i; j<=x; j = j + i){
            num[j] = 0;
        }    
    }    
}    

最后,你想达到 50 亿,这超出了 uint32_t(我的系统上是 unsigned long int)的范围,即 42 亿。如果这会让您满意,请将int 定义更改为unsigned,注意循环控件不会换行,即使用unsigned x = UINT_MAX - 1;

如果您没有可用的 5Gb 内存,请按照@BoPersson 的建议使用位状态。

【讨论】:

  • 谢谢。问题在于 i*i 打破了限制,而不是数组。工作完成:)
  • @PanagiotisPapantonakis 或许请您投票或“接受”?
  • @PanagiotisPapantonakis 谢谢 - 不要忘记您确实需要 x+1 数组大小。
【解决方案2】:

以下代码检查错误,使用高达 5000000000 的值进行测试,正确输出素数的最终计数,使用 malloc 以避免超出可用堆栈空间。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    unsigned long int x,i, j;
    unsigned prime = 0;
    scanf("%lu", &x);

    char *num = malloc( x);
    if( NULL == num)
    {
        perror( "malloc failed");
        exit(EXIT_FAILURE);
    }


    for(i=0; i<x;i++)
    {
      num[i]=1;
    }

    for(i=2; i<x;i++)
    {
      if(num[i] == 1)
      {
        for(j=i*i; j<x; j = j + i)
        {
          num[j] = 0;
        }
        //printf("num[%lu]\n", i);
        prime++;
      }
    }
     printf("%u\n", prime);
     return 0;
}

【讨论】:

    猜你喜欢
    • 2022-01-08
    • 2018-08-15
    相关资源
    最近更新 更多