使用集合计算素数,C++

Posted

技术标签:

【中文标题】使用集合计算素数,C++【英文标题】:Calculating Prime Numbers using Sets, C++ 【发布时间】:2015-12-22 19:17:35 【问题描述】:

我正在尝试使用一个集合来计算素数,但是当我进行计算时,我的迭代器随机跳跃。

我正在尝试为 N=10 的值实现此方法。

选择一个整数 n。此函数将计算所有素数 到 n.首先将从 1 到 n 的所有数字插入到一个集合中。然后全部抹去 2 的倍数(2 除外);即 4, 6, 8, 10, 12, .... 全部擦除 3 的倍数,即 6, 9, 12, 15, ... 。上升到 sqrt(n) 。这 剩下的数字都是素数。

当我运行我的代码时,它会删除 1 然后 pos 跳转到 4?我不确定为什么会发生这种情况,而不是转到值 2,即集合中的第二个值?

在我删除迭代器指向的值后会发生什么,迭代器指向什么,如果我将它推进它会推进到哪里?

代码如下:

set<int> sieveofEratosthenes(int n) //n = 10

    set<int> a;
    set<int>::iterator pos = a.begin();

//generate set of values 1-10
    for (int i = 1; i <= n; i++) 
        a.insert(i);
        if(pos != a.end())
            pos++;
    

    pos = a.begin();

    //remove prime numbers
    while (pos != a.end())
    
        cout << "\nNew Iteration \n\n";

        for (int i = 1; i < sqrt(n); i++) 
            int val = *pos%i;

            cout << "Pos = " << *pos << "\n";
            cout << "I = " << i << "\n";
            cout << *pos << "/" << i << "=" << val << "\n\n";

            if (val == 0) 
                a.erase(i);
                
            
        pos++;
    
    return a;

【问题讨论】:

埃拉托色尼筛法不使用任何形式的可分性测试。您可以在根本不知道任何算术的情况下手动执行它。 【参考方案1】:

您的实现不正确,因为它试图将筛算法与尝试除数的简单算法结合起来,但没有成功。您不需要测试可除性来实现筛子 - 事实上,这是算法美观的主要贡献者!你甚至不需要乘法。

a.erase(1);
pos = a.begin();
while (pos != a.end()) 
    int current = *pos++;
    // "remove" is the number to remove.
    // Start it at twice the current number
    int remove = current + current;
    while (remove <= n) 
        a.erase(remove);
        // Add the current number to get the next item to remove
        remove += current;
    

Demo.

【讨论】:

不错! while (pos != a.end() &amp;&amp; (*pos) * (*pos) &lt; n) 也将满足“上升到 sqrt(n)”的要求。 *pos++ 是不是先赋值给 current 然后再递增? @user2076774 *pos++ 的行为就像一个指针:它在迭代器pos 处产生当前值,然后将递增的值存储到迭代器中。【参考方案2】:

在循环中擦除元素时,您必须小心索引。例如,当您擦除位置 0 处的元素时,下一个元素现在位于位置 0。因此循环应如下所示:

    for (int i = 1; i < sqrt(n); /*no increment*/) 
        /* ... */
        if (val == 0) 
            a.erase(i);
         else 
            i++;
        
    

实际上,您还必须注意在擦除元素时集合的大小正在缩小。因此,您最好使用迭代器:

    for (auto it = a.begin(); i != a.end(); /*no increment*/) 
        /* ... */
        if (val == 0) 
            a.erase(it);
         else 
            it++;
        
    

PS:以上内容并不完全是您对筛子所需要的,但它应该足以演示如何擦除元素(我希望如此)。

【讨论】:

以上是关于使用集合计算素数,C++的主要内容,如果未能解决你的问题,请参考以下文章

Python 集合理解

给定素数 N,计算下一个素数?

c语言中有没有比较简单的算法来判断两个集合有交集

素数杨辉三角封装结构和集合操作(16)——集合及操作

黑马基础阶段测试题:创建一个存储字符串的集合list,向list中添加以下字符串:”C++””Java”” Python””大数据与云计算”。遍历集合,将长度小于5的字符串从集合中删除,删除成功(代码

用 C++ 中的 AKS 素性测试计算孪生素数我做错了啥?