简体   繁体   English

修复我在C ++中实现Eratosthenes筛子的实现

[英]Fixing my implementation of Sieve of Eratosthenes in C++

My algorithm runs correctly up to the first 100 primes but then something goes wrong. 我的算法可以正确运行直到前100个素数,但是出了点问题。 Please have a look at my code below, I tried to follow the pseudo-code given here https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes 请在下面查看我的代码,我尝试遵循此处给出的伪代码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;
}

The output is: 输出为:

2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
193
199

I'm absolutely amazed the program runs at all. 我完全惊讶该程序完全运行。 It has an absolute truckload of undefined behaviour !. 它具有不确定行为的绝对负载 !。

Unless I'm very much mistaken (in which case please reward the serenity of my Friday afternoon with downvotes), vector<bool> p(true, n) is creating a vector of size true , with the elements initialised to n . 除非我非常误解(在这种情况下,请用下降投票来奖励星期五下午的宁静),否则vector<bool> p(true, n)将创建一个大小为true的向量,并将元素初始化为n

You have the constructor arguments the wrong way round. 您有错误的构造函数参数。 This is effectively reversing the sieve for most of the values. 这可以有效地反转大多数值的筛子。

Have you absolutely clobbered your compiler's warning level? 您是否绝对破坏了编译器的警告级别?

First of all, you do not need to store a boolean value for each and every number. 首先,您不需要为每个数字存储一个布尔值。 This way, you are wasting memory. 这样,您在浪费内存。 You should store only the found primes instead, unless you have a very good reason not to do so. 您应该只存储找到的素数,除非您有很好的理由不这样做。

I will not implement the code, since it would spoil the joy of learning. 我不会执行代码,因为它会破坏学习的乐趣。 You should implement the following: 您应该实现以下内容:

  • Initialize p as a vector of integers. p初始化为整数向量。
  • Store 2 as first value inside p 将2作为第一个值存储在p
  • Iterate all odd numbers starting from 3 and ending at the end number 迭代所有从3到结束号的奇数
  • For each number, calculate its square root and store it into a variable 对于每个数字,计算其平方根并将其存储到变量中
  • Iterate all previous elements of the p until you reach a divisor or the value of the vector at the given index reaches the square root, starting from the second element, as pair numbers larger than 2 are ignored 迭代p所有先前元素,直到达到除数,或者给定索引处的矢量的值从第二个元素开始达到平方根,因为对数大于2的对将被忽略
  • If you find a divisor inside your inner loop, store it into your vector and get out of the inner loop 如果在内部循环中发现除数,则将其存储到向量中并退出内部循环

At the end you will have a vector of primes, indexes will mean the prime index and the values will be actual primes. 最后,您将有一个素数vector ,索引将表示素数索引,而值将是实际素数。 Each element will be a prime of its own. 每个元素都是它自己的素数。

You mess your numbering up. 你把号码弄乱了。 If p[k] is the primeness of number k+1 , your for loop is wrong 如果p[k]是数k+1的素数,则您的for循环是错误的

for(int j = i*i; j < n; j += i)

and should be 并且应该是

for(int j = (i-1)*(i-1); j < n; j += (i-1))

My advice would be to use more informative variable names and avoid those sources of confusion like p[k] giving information about integer k+1 . 我的建议是使用更多信息量大的变量名,避免像p[k]这样的混淆源给出有关整数k+1

Your vector construction is wrong. 您的向量构造是错误的。 It must be 一定是

vector<bool> p(n, true); //all values set to true, from 0 to n

instead of 代替

vector<bool> p(true, n); //all values set to true, from 0 to n   

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM