【问题标题】:Sieve of Eratosthenes C++ Infinite Loop埃拉托色尼筛法 C++ 无限循环
【发布时间】:2015-10-15 20:45:50
【问题描述】:

所以,我一直在解决 Bjarne Stroustrup 的《编程:为我自己的利益使用 C++ 的原则和实践》中的一个问题,这个问题已经困扰了我好几天了。

我应该使用第 4 章学到的工具来实现经典的埃拉托色尼筛算法(这不是很多),这就是我目前所拥有的:

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

int main()
{
    int p = 2;
    int n = 0;
    vector<int> nums{ 1, 1 };

    cout << "Enter an integer greater than 1:\n";
    cin >> n;

    for (int i = 2; i <= n; ++i)
        nums.push_back(0);

    while (p < sqrt(n))
    {
        for (int i = 2; (i*p) <= n; ++i)
        {
            nums[i*p] = 1;
        }

        for (int i = (p+1); i <= n; ++i)
        {
            if (nums[i] == 0)
            {
                p = i;
                break;
            }
        }
    }

    for (int i = 0; i <= n; ++i)
    {
        if (nums[i] == 0)
            cout << i << '\n';
    }

    return 0;
}

此代码非常接近工作,但没有雪茄。它只打印包含 5 之后的素数,它不打印 2 或 3。我知道问题是由于我的标记循环正在标记 nums[2] 和 nums[3],所以我尝试添加以下代码行以确保未标记 2 和 3,因为它们被用作 p 起始值:

nums[p] = 0;

我把这条线放在嵌套在 while 循环中的两个 for 循环之间。我不知道怎么做,但这会导致我尝试了几个小时来修复的无限循环。我真的是无能为力了。

注意:我一直在用 n = 23 进行测试。

【问题讨论】:

  • 因为您的标记for 循环从0 开始,每次您找到一个素数时,它也会将0p 标记为非素数。在您的情况下,由于5&gt;sqrt(23),标记循环不会针对任何大于3 的素数运行,这就是您将这些素数取回的原因,但23 是不幸的:-)
  • 感谢您的评论。不幸的是,让我的标记循环从 i = 2 开始也会让我陷入无限循环!
  • 当您进行重要更正时,例如将i=0 更改为i=2,并且代码仍然无法正常工作,请编辑您的原始帖子以显示您现在需要帮助的版本。不要只告诉我们您已纠正了该错误,让我们猜测您是否正确纠正了它。
  • 我认为nums{ 1 1 } 表示长度为 1 且值为 1。但我怀疑您希望元素 0 和 1 都为 1。
  • 这是因为在标记循环之后的循环中,您开始从0 中寻找第一个素数,这将始终是2。所以你总是标记2 的倍数并且永远不会得到大于2p。在第二个for 循环中,从p + 1 开始搜索下一个素数。

标签: c++ visual-studio sieve-of-eratosthenes


【解决方案1】:

所以,在确定你的第一个循环起点之后,问题是下一个循环。

因为下一个循环总是从0 开始并寻找下一个素数,所以它总是会找到2,这将导致无限循环。

要解决此问题,请从上一个值开始搜索下一个素数:

    for(int i = p + 1; i <= n; ++i)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    • 2016-10-29
    • 1970-01-01
    相关资源
    最近更新 更多