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