筛选 Eratosthenes 素数高达一百万 c++

Posted

技术标签:

【中文标题】筛选 Eratosthenes 素数高达一百万 c++【英文标题】:Sieve of Eratosthenes prime numbers up to a million c++ 【发布时间】:2015-03-28 18:10:38 【问题描述】:

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

实施埃拉托色尼筛法并用它找出所有素数 小于或等于一百万的数字。使用结果 证明哥德巴赫猜想对四到四之间的所有偶数 一百万,包括在内。

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

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

这个函数接受一个整数数组作为它的参数。数组 应初始化为值 1 到 1000000。 函数修改数组,以便只保留素数; 所有其他值都归零。

必须编写此函数以接受任何整数数组 尺寸。您必须输出 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;
            
        
    

【问题讨论】:

int array[num]; 请改用std::vector&lt;int&gt; array(num);。您的堆栈大小可能太小而无法分配这么大的数组。 我还没有学会如何使用向量。不过谢谢你的回复! 您也可以使用int* array = new int[n]; 自己管理分配的堆内存。但要小心。 请查看these search results。 【参考方案1】:

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

int array[num];

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

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

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

    您将用于程序的堆栈大小配置为足够大以容纳 int 元素的数量(这取决于操作系统) 您改用std::vector&lt;int&gt; array(num);,它将这些元素分配到堆内存中 您在程序结束时使用int* array = new int[num];delete [] array; 自己在堆上分配必要的内存(我不推荐这种解决方案,因为在正确的内存管理方面很容易犯愚蠢的错误)李>

【讨论】:

我不明白如何将向量实现到我的程序中。感谢您的回复! @Bawad 如图,并将std::vector::data()作为参数传递给其他函数。 @Bawad 哪个错误?你错过#include &lt;vector&gt;了吗? 我不是在玩负鼠先生,哈哈。我只是不明白。我相信你是个很聪明的人。我对编程很陌生。 @πάντα ῥεῖ @Bawad 那么你为什么接受这个答案呢?你的错误是什么?你不明白什么?【参考方案2】:

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

为什么不使用位数组呢?

做类似的事情

#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) 评估为假,则x 是素数。

节省大量内存。

EDIT1:

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

EDIT2:

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

【讨论】:

以上是关于筛选 Eratosthenes 素数高达一百万 c++的主要内容,如果未能解决你的问题,请参考以下文章

Eratosthenes筛选法构造1-n 素数表

关于Eratosthenes筛子算法筛选小于n的素数的理解

algorithm@ Sieve of Eratosthenes (素数筛选算法) & Related Problem (Return two prime numbers )

质数筛选法:Eratosthenes筛选法与欧拉筛选法

小航的算法日记素数筛选

素数筛选法