简体   繁体   English

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

[英]Sieve of Eratosthenes prime numbers up to a million c++

So I need help with my code. 所以我需要帮助我的代码。 For some reason it keeps crashing when I enter a number past 500,000. 出于某种原因,当我输入超过500,000的数字时,它会一直崩溃。 Here is the exact assignment. 这是确切的任务。

Implement the Sieve of Eratosthenes and use it to find all prime numbers less than or equal to one million. 实施Eratosthenes筛选并使用它来查找小于或等于一百万的所有素数。 Use the result to prove Goldbach's Conjecture for all even integers between four and one million, inclusive. 使用结果证明Goldbach的猜想适用​​于所有包含四到一百万的整数。

Implement a function with the following declaration: 使用以下声明实现一个函数:

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

This function takes an integer array as its argument. 此函数将整数数组作为其参数。 The array should be initialized to the values 1 through 1000000. The function modifies the array so that only the prime numbers remain; 应该将数组初始化为值1到1000000.该函数修改数组,以便只保留素数; all other values are zeroed out. 所有其他值都归零。

This function must be written to accept an integer array of any size. 必须编写此函数以接受任何大小的整数数组。 You must should output for all primes numbers between 1 and 1000000, but when I test your function it may be on an array of a different size. 您必须输出1到1000000之间的所有素数,但是当我测试您的函数时,它可能在不同大小的数组上。

Implement a function with the following declaration: 使用以下声明实现一个函数:

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

This function takes the same argument as the previous function and displays each even integer between 4 and 1000000 with two prime numbers that add to it. 此函数采用与前一个函数相同的参数,并显示4到1000000之间的每个偶数整数,并添加两个素数。

The goal here is to provide an efficient implementation. 这里的目标是提供有效的实施。 This means no multiplication, division, or modulus when determining if a number is prime. 这意味着在确定数字是否为素数时没有乘法,除法或模数。 It also means that the second function must find two primes efficiently. 这也意味着第二个函数必须有效地找到两个素数。

Output for your program: 您的计划的输出:

All prime numbers between 1 and 1000000 and all even numbers between 4 and 1000000 and the two prime numbers that sum up to it. 所有素数在1到1000000之间,所有偶数在4到1000000之间,两个素数总和到它。

DO NOT provide output or a session record for this project! 不要为此项目提供输出或会话记录!

And here is what I have so far. 这是我到目前为止所拥有的。 If anyone could help me that would be great. 如果有人能帮助我那会很棒。

#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;
            }
        }
    }
}

The reason why your code crashes is that you're using VLA allocation for the array here 你的代码崩溃的原因是你在这里使用了数组的VLA分配

int array[num];

It's used to allocate num int elements of the stack, which is most probably too small to hold a million of int values. 它用于分配堆栈的num int元素,这可能太小而无法容纳一百万个int值。

You should note it's not a standard c++ feature, but an extension provided by a number of compiler implementations. 您应该注意它不是标准的c ++特性,而是由许多编译器实现提供的扩展。

To fix this there are three alternatives: 要解决这个问题,有三种选择:

  1. You configure the stack size used for your program to be big enough to hold the number of int elements (this is OS dependend) 您将用于程序的堆栈大小配置为足以容纳int元素的数量(这是OS dependend)
  2. You use a std::vector<int> array(num); 你使用std::vector<int> array(num); instead, that allocates these elements on the heap memory 相反,它在堆内存上分配这些元素
  3. You allocate the necessary memory on the heap yourself using int* array = new int[num]; 您可以使用int* array = new int[num];在堆上自己分配必要的内存int* array = new int[num]; and delete [] array; delete [] array; at the end of your program (I wouldn't recommend this solution, because it's prone to make silly mistakes regarding the proper memory management) 在你的程序结束时(我不推荐这个解决方案,因为它很容易在正确的内存管理方面犯愚蠢的错误)

As I see this is an assignment, you need to write your own code, but I have a few ideas to reduce the amount of memory significantly. 我认为这是一项任务,你需要编写自己的代码,但我有一些想法可以显着减少内存量。

Why don't you use array of bits instead ? 你为什么不使用比特数组呢?

Do something like 做点什么

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

and define arr as an array of char . 并将arr定义为char数组。 This will make the memory utilization 8 folds down. 这将使内存利用率降低8倍。 For C++ you can use bool might not get you the lowest possible memory usage. 对于C ++,您可以使用bool可能无法获得尽可能低的内存使用量。

First clear out all the char elements. 首先清除所有char元素。 Then for each number set bits using SET(x) an once all marking is done. 然后,对于使用SET(x)的每个数字设置位,一次完成所有标记。 If IS_SET(x) evaluates false then x is prime. 如果IS_SET(x)计算为false,则x为prime。

Saves large amount of memory. 节省大量内存。

EDIT1: EDIT1:

Another trick to cut 50% of the memory required is not to retain space for the even numbers. 削减50%所需内存的另一个技巧是不为常数保留空间。 Start with i=3 and always increment using i+=2 and mark the bit arrays. i=3开始,并始终使用i+=2递增并标记位数组。 While reading do the same. 虽然阅读也是如此。

EDIT2: EDIT2:

If you can find a series which skips the integers which are multiple of two or three or both, then you can save around 30% more memory. 如果你能找到一个跳过两个或三个或两者的倍数的整数的系列,那么你可以节省大约30%的内存。 In fact you can make such a series and skip storing and marking for the multiples of two and three or both. 事实上,你可以制作这样一个系列,并跳过存储和标记两个和三个或两个的倍数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM