Eratosthenes的筛子数量高达一百万c ++

时间:2015-03-28 18:10:38

标签: c++ sieve-of-eratosthenes

所以我需要帮助我的代码。出于某种原因,当我输入超过500,000的数字时,它会一直崩溃。这是确切的任务。

  

实施Eratosthenes筛选并使用它来查找所有素数   数字小于或等于一百万。使用结果   证明了哥德巴赫猜想所有甚至四和四的整数   一百万,包括在内。

     

使用以下声明实现一个函数:

void sieve(int array[], int num);
     

此函数将整数数组作为其参数。阵列   应该初始化为1到1000000的值   函数修改数组,以便只保留素数;   所有其他值都归零。

     

必须编写此函数以接受任何整数数组   尺寸。您必须输出1到1之间的所有素数   1000000,但是当我测试你的函数时,它可能在一个数组上   不同的大小。

     

使用以下声明实现一个函数:

void goldbach(int array[], int num);
     

此函数采用与上一个函数相同的参数   并显示4到1000000之间的每个偶数整数和两个   添加到它的素数。

     

这里的目标是提供有效的实施。这个   在确定是否时,表示没有乘法,除法或模数   一个数字是素数。这也意味着第二个功能必须找到   两个素数有效。

     

您的计划的输出:

     

1到1000000之间的所有素数   以及4到1000000之间的所有偶数和两个素数   总结它的数字。

     

请勿为此项目提供输出或会话记录!

这是我到目前为止所拥有的。如果有人能帮助我那会很棒。

#include <iostream>
using namespace std;

void sieve (int array[], int num);

int main()
{
    int num;
    cout << "Enter a number to calculate up to." << endl;
    cin>> num;
    if ( num < 2 )
        return 0;

    int array[num];
    array[0]= array[1]= 0;
    for ( int i= 2; i < num; ++i )
        array[i]= i;
    sieve(array,num);
    for (int i=0; i<num; i++)
        if (array[i] > 0)
            cout << array[i] <<" "<<endl;
    cout<<endl;

    return 0;
}

void sieve( int array[], int num )
{
    for ( int i= 0; i < num; ++i )
    {
        if ( array[i] != 0 )
        {
            for ( int j= i+i; j < num; j += i )
            {
                array[j]= 0;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:3)

你的代码崩溃的原因是你在这里使用VLA分配

int array[num];

它用于分配堆栈的num个int元素,这个元素很可能太小而无法容纳一百万int个值。

您应该注意它不是标准的c ++特性,而是由许多编译器实现提供的扩展。

要解决此问题,有三种选择:

  1. 您可以将用于程序的堆栈大小配置为足以容纳int元素的数量(这是操作系统依赖)
  2. 您使用std::vector<int> array(num);代替,在堆内存上分配这些元素
  3. 您在程序结束时使用int* array = new int[num];delete [] array;自己在堆上分配必要的内存(我不建议使用此解决方案,因为它很容易在正确的内存中犯下愚蠢的错误管理)

答案 1 :(得分:1)

我认为这是一项任务,你需要编写自己的代码,但我有一些想法可以显着减少内存量。

为什么不使用数组?

执行类似

的操作
#define IS_SET(x) (arr[(x)>>3] & (0x01 << ((x) & 0x07)))
#define SET(x) (arr[(x)>>3] |= (0x01 << ((x) & 0x07)))

并将arr定义为char的数组。这将使内存利用率降低8倍。对于C ++,您可以使用bool可能无法获得尽可能低的内存使用量。

首先清除所有char元素。然后使用SET(x)对每个数字设置位进行一次所有标记。如果IS_SET(x)评估为false,则x为素数。

节省大量内存。

<强> EDIT1:

削减50%所需内存的另一个技巧是不保留偶数的空间。从i=3开始,并始终使用i+=2递增并标记位数组。虽然阅读也是如此。

<强> EDIT2:

如果你能找到一个跳过两个或三个或两者的倍数的整数的系列,那么你可以节省大约30%的内存。事实上,你可以制作这样一个系列,并跳过存储和标记两个和三个或两个的倍数。