修复我在 C++ 中的埃拉托色尼筛法的实现
Fixing my implementation of Sieve of Eratosthenes in C++
我的算法在前 100 个素数前都正确运行,但随后出现问题。请看下面我的代码,我试着按照这里给出的伪代码 https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main()
{
int n = 1000; //compute primes up to this number
vector<bool> p(true,n); //all values set to true, from 0 to n
for(int i = 2; i < sqrt(n)+1; i++){
if( p[i-1] == true ){
for(int j = i*i; j < n; j += i) //start looking for multiples of prime i at i*i (optimized)
p[j-1] = false;
}
}
for(int i = 2; i < n; i++){
if( p[i-1] == true )
cout << i << "\n";
}
return 0;
}
输出为:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
193
199
你把编号弄乱了。如果 p[k]
是数 k+1
的素数,你的 for 循环是错误的
for(int j = i*i; j < n; j += i)
应该是
for(int j = (i-1)*(i-1); j < n; j += (i-1))
我的建议是使用信息量更大的变量名,避免混淆来源,例如 p[k]
提供有关整数的信息 k+1
。
我对程序的运行感到非常惊讶。它的绝对 卡车负载 为 未定义行为 !。
除非我大错特错(在这种情况下,请用反对票来奖励我周五下午的宁静),vector<bool> p(true, n)
正在创建一个大小为 true
的向量,其中的元素初始化为n
.
你用错了构造函数参数。这实际上是对大多数值进行反筛。
您是否完全破坏了编译器的警告级别?
你的向量构建是错误的。必须是
vector<bool> p(n, true); //all values set to true, from 0 to n
而不是
vector<bool> p(true, n); //all values set to true, from 0 to n
首先,您不需要为每个数字存储一个布尔值。这样,您就是在浪费内存。您应该只存储找到的素数,除非您有充分的理由不这样做。
我不会实现代码,因为它会破坏学习的乐趣。您应该执行以下操作:
- 将
p
初始化为整数向量。
- 将 2 作为第一个值存储在
p
中
- 遍历所有从3开始到尾数结束的奇数
- 对于每个数字,计算其平方根并将其存储到变量中
- 迭代
p
的所有先前元素,直到达到除数或给定索引处的向量值达到平方根,从第二个元素开始,因为大于 2 的对数将被忽略
- 如果您在内部循环中找到除数,将其存储到向量中并退出内部循环
最后你将得到一个 vector
个素数,索引将表示素数索引,值将是实际素数。每个元素都是它自己的素数。
我的算法在前 100 个素数前都正确运行,但随后出现问题。请看下面我的代码,我试着按照这里给出的伪代码 https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main()
{
int n = 1000; //compute primes up to this number
vector<bool> p(true,n); //all values set to true, from 0 to n
for(int i = 2; i < sqrt(n)+1; i++){
if( p[i-1] == true ){
for(int j = i*i; j < n; j += i) //start looking for multiples of prime i at i*i (optimized)
p[j-1] = false;
}
}
for(int i = 2; i < n; i++){
if( p[i-1] == true )
cout << i << "\n";
}
return 0;
}
输出为:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
193
199
你把编号弄乱了。如果 p[k]
是数 k+1
的素数,你的 for 循环是错误的
for(int j = i*i; j < n; j += i)
应该是
for(int j = (i-1)*(i-1); j < n; j += (i-1))
我的建议是使用信息量更大的变量名,避免混淆来源,例如 p[k]
提供有关整数的信息 k+1
。
我对程序的运行感到非常惊讶。它的绝对 卡车负载 为 未定义行为 !。
除非我大错特错(在这种情况下,请用反对票来奖励我周五下午的宁静),vector<bool> p(true, n)
正在创建一个大小为 true
的向量,其中的元素初始化为n
.
你用错了构造函数参数。这实际上是对大多数值进行反筛。
您是否完全破坏了编译器的警告级别?
你的向量构建是错误的。必须是
vector<bool> p(n, true); //all values set to true, from 0 to n
而不是
vector<bool> p(true, n); //all values set to true, from 0 to n
首先,您不需要为每个数字存储一个布尔值。这样,您就是在浪费内存。您应该只存储找到的素数,除非您有充分的理由不这样做。
我不会实现代码,因为它会破坏学习的乐趣。您应该执行以下操作:
- 将
p
初始化为整数向量。 - 将 2 作为第一个值存储在
p
中
- 遍历所有从3开始到尾数结束的奇数
- 对于每个数字,计算其平方根并将其存储到变量中
- 迭代
p
的所有先前元素,直到达到除数或给定索引处的向量值达到平方根,从第二个元素开始,因为大于 2 的对数将被忽略 - 如果您在内部循环中找到除数,将其存储到向量中并退出内部循环
最后你将得到一个 vector
个素数,索引将表示素数索引,值将是实际素数。每个元素都是它自己的素数。