当前位置: 首页 > 知识库问答 >
问题:

大量埃拉托色尼筛c

纪正德
2023-03-14

就像这个问题一样,我也在厄拉多塞的筛子上工作。同样来自《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;
}

现在,我怎样才能在输入的中处理真正的大数字?无符号int类型应该允许我输入2^32=4,294,967,296的数字。但是我不能,我运行内存溢出。是的,我已经计算过了:存储2^32量的int,每个32位。所以32/8*2^32=16 GiB的内存。我只有4 GiB……

所以我在这里真正做的是将非素数设置为零。所以我可以使用布尔值。但是,它们仍然需要8位,每个字节。理论上,我可以达到无符号整数的限制(8/8*2^32=4 GiB),使用我的一些操作系统交换空间和开销。但是我有一台x86_64的PC,那么大于2^32的数字呢?

知道质数在密码学中很重要,一定有更有效的方法来做到这一点?还有没有方法可以优化找到所有这些质数所需的时间?

共有2个答案

刘运浩
2023-03-14

你问了几个不同的问题。

对于高达2**32的素数,筛分是合适的,但您需要分段工作,而不是在一个大博客中工作。我在这里的答案告诉了如何做到这一点。

对于非常大的密码素数,该过程是挑选一个数,然后使用概率测试来测试它的素性,例如米勒-拉宾测试或贝利-瓦格斯塔夫测试。这个过程并不完美,有时可能会选择复合而不是质数,但这种情况非常罕见。

江佐
2023-03-14

在存储的意义上,您可以使用 std::向量

注意:使用下面的代码示例测试程序,输入80亿的数量,导致程序运行时内存使用量大约为。975 MiB,证明理论数。

您还可以获得一些时间,因为您可以一次声明完整向量,而无需迭代:向量

此外,一旦你顺着筛子找到了数量的平方根,所有仍然为真的数字都是质数。插入<代码> if (p * p

编辑:在最后一个循环中,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,147,483,647个素数。我的代码工作正常,可以生成大约10,000,000个,但是当我增加数组的大小以容纳更大的数字时,它失败了。有人能指导我如何用c语言(不是c语言)使用位向量吗?谢谢 这是我的代码:

  • 我正在尝试让我的埃拉托斯特尼筛程序仅输出用户请求的前n个素数。Sieve本身工作得很好 - 它正确地输出了前100个素数(如下面的数组所示),但是最后一个循环中的计数器变量无法正常工作,我无法找出原因。例如,如果用户输入“5”表示 n,则只会打印前 3 个定焦值。 有人可以帮我找出我的错误吗?我的目的是让“count”成为一个非常简单的计数器,每次都会增加1,直到它达到n。

  • 我正在尝试对厄拉多塞的筛子进行并行实现。我做了一个布尔列表,对于给定的大小,用true填充。无论何时发现一个素数,该素数的所有倍数在布尔列表中都被标记为假。 我试图使这个算法并行的方法是在仍然过滤初始质数的同时启动一个新线程。例如,算法从素数 = 2 开始。在 for 循环中,当素数 * 素数时,我做另一个 for 循环,其中检查素数 (2) 和素数 * 素数 (4) 之间的每个数字。如果布尔列表

  • 我正在做一个C程序,用厄拉多塞筛寻找质数 目前我有以下代码: C 这工作正常,即它说在1和100之间有25个素数(这是正确的)。但是,例如,如果我想知道前500个素数,它会说有118个,而实际上有95个。为了解决这个问题,我必须添加更多的倍数来删除,然后添加更多。 有没有一种方法可以使它更有效,而不仅仅是让它去除以前发现的素数的更多倍数?

  • 我有一个< code >无符号int的位数组< code>prime[]。我希望用这个数组实现一个厄拉多塞筛,让每一位代表一个数。也就是说,给定< code>n,保存对应于< code>n的位的数组元素将是< code>prime[n/32],并且特定位将在位置< code>n2中。 我的函数在数字为素数时返回1(如果其位==0),否则返回0: 我的< code>setBit(int n)函数只是

  • 我正在尝试编写一个程序来实现对埃拉托西的筛选。我可以从2到任何给定的结束编号,但我们正在处理的赋值要求我们输入起始值。我完全被卡住了。我试过很多不同的代码,但它总是给我奇怪的答案。 我的起点是起始值,终点是结束值。我基本上想找到这个范围的素数。谢谢!!!