[英]Sieve of Eratosthenes for large numbers c++
就像这个问题一样 ,我也在研究Eratosthenes的筛子。 同样从《使用c ++进行编程的原理和实践》一书的第4章中。我能够正确地实现它,并且它可以按照练习要求正确地起作用。
#include <iostream>
#include <vector>
using namespace std;
int main() {
unsigned int amount = 0;
cin >> amount;
vector<int>numbers;
for (unsigned int i = 0; i <= amount; i++) {
numbers.push_back(i);
}
for (unsigned int p = 2; p < amount; p++) {
if (numbers[p] == 0)
continue;
cout << p << '\n';
for (unsigned int i = p + p; i <= amount; i += p) {
numbers[i] = false;
}
}
return 0;
}
现在,我将如何处理输入amount
中的实数? unsigned int
类型应允许我输入2 ^ 32 = 4,294,967,296的数字。 但是我不能,我用光了内存。 是的,我已经完成了数学运算:存储2 ^ 32数量的int,每个整数32位。 因此,32/8 * 2 ^ 32 = 16 GiB的内存。 我只有4个GiB ...
所以我在这里真正要做的是将非素数设置为零。 所以我可以使用布尔值。 但是,它们将占用8位,因此每个占用1个字节。 理论上,我可以将一些交换空间用于操作系统和开销,从而达到unsigned int
(8/8 * 2 ^ 32 = 4 GiB)的极限。 但是我有一台x86_64 PC,那么大于2 ^ 32的数字呢?
在存储方面,您可以使用std::vector<bool>
容器。 由于它的工作方式,您必须牺牲存储速度 。 因为此实现每个布尔值一位,所以存储效率提高了8倍。 如果您有足够的RAM用于该程序,则应该有可能获得接近8 * 4,294,967,296的数字。 您唯一需要做的就是使用unsigned long long
释放64位数字的可用性。
注意 :使用下面的代码示例测试该程序,输入的金额为80亿,导致该程序在运行时的内存使用量大约为80。 975 MiB,证明了理论值。
您还可以获得一些时间,因为您可以一次声明完整的向量,而无需迭代: vector<bool>numbers (amount, true);
创建一个大小等于输入量的向量,并将所有元素设置为true。 现在,您可以调整代码以将非素数设置为false而不是0。
此外,一旦遵循筛子直到数量的平方根,所有保持为真的数字都是质数。 在输出素数之后,插入if (p * p >= amount)
作为其他继续条件。 同样,这对于您的处理时间来说是微不足道的改进。
编辑 :在最后一个循环中,可以p
求平方,因为直到p
的平方为止的所有数字都已被先前的数字证明不是素数。
总之,您应该得到如下内容:
#include <iostream>
#include <vector>
using namespace std;
int main() {
unsigned long long amount = 0;
cin >> amount;
vector<bool>numbers (amount, true);
for (unsigned long long p = 2; p < amount; p++) {
if ( ! numbers[p])
continue;
cout << p << '\n';
if (p * p >= amount)
continue;
for (unsigned long long i = p * p; i <= amount; i += p) {
numbers[i] = false;
}
}
return 0;
}
您问了几个不同的问题。
对于不超过2 ** 32的素数,筛分是适当的,但是您需要分段操作而不是在一个大博客中工作。 我在这里的答案告诉您如何执行此操作。
对于非常大的密码素数,过程是选择一个数字,然后使用诸如Miller-Rabin检验或Baillie-Wagstaff检验之类的概率检验来测试其素数。 这个过程并不完美,有时可能会选择复合词而不是素词,但是这种情况很少见。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.