筛选 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<int> array(num);
。您的堆栈大小可能太小而无法分配这么大的数组。
我还没有学会如何使用向量。不过谢谢你的回复!
您也可以使用int* array = new int[n];
自己管理分配的堆内存。但要小心。
请查看these search results。
【参考方案1】:
你的代码崩溃的原因是你在这里为数组使用了VLA分配
int array[num];
它用于分配堆栈的num
int 元素,这很可能太小而无法容纳一百万个int
值。
您应该注意,它不是标准的 c++ 功能,而是许多编译器实现提供的扩展。
要解决此问题,有三种选择:
-
您将用于程序的堆栈大小配置为足够大以容纳
int
元素的数量(这取决于操作系统)
您改用std::vector<int> array(num);
,它将这些元素分配到堆内存中
您在程序结束时使用int* array = new int[num];
和delete [] array;
自己在堆上分配必要的内存(我不推荐这种解决方案,因为在正确的内存管理方面很容易犯愚蠢的错误)李>
【讨论】:
我不明白如何将向量实现到我的程序中。感谢您的回复! @Bawad 如图,并将std::vector::data()
作为参数传递给其他函数。
@Bawad 哪个错误?你错过#include <vector>
了吗?
我不是在玩负鼠先生,哈哈。我只是不明白。我相信你是个很聪明的人。我对编程很陌生。 @πάντα ῥεῖ
@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++的主要内容,如果未能解决你的问题,请参考以下文章
algorithm@ Sieve of Eratosthenes (素数筛选算法) & Related Problem (Return two prime numbers )