修复我在 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 个素数,索引将表示素数索引,值将是实际素数。每个元素都是它自己的素数。