我一直在尝试创建一个 C++ 程序来使用Eratosthenes 算法的 Sieve来查找某个整数 n 下的所有素数,如下所示:
创建一个从 2 到 n 的整数向量。
从向量的最小元素 2 开始,将其添加到新的素数向量中,并从整数向量中删除 2 的所有倍数。
对整数向量的新的最小元素(即 3)重复此过程并重复此过程,直到整数向量为空。素数向量然后包含所有需要的素数。
现在,此代码有效:
#include <iostream>
#include <algorithm>
#include <vector>
void printVector(std::vector<int> v){
for(int i: v)std:: cout << i << " ";
std::cout << std::endl;
}
std::vector<int> primesBelow(int n){
std::vector<int> primes {}, integers {};
for(int i = 2; i <= n; i++) integers.push_back(i); //list elements 2 to n
auto ptr = integers.begin(); //pointer to smallest element
while(ptr != integers.end()){
int p = *ptr;
primes.push_back(p);
integers.erase(std::remove_if(integers.begin(), integers.end(), [=](int x){return x%p==0;}), integers.end());
ptr = integers.begin();
}
return primes;
}
int main() {
auto v = primesBelow(100);
printVector(v);
return 0;
}
但是,以下代码不起作用(唯一的区别在于while
循环):
#include <iostream>
#include <algorithm>
#include <vector>
void printVector(std::vector<int> v){
for(int i: v)std:: cout << i << " ";
std::cout << std::endl;
}
std::vector<int> primesBelow(int n){
std::vector<int> primes {}, integers {};
for(int i = 2; i <= n; i++) integers.push_back(i); //list elements 2 to n
auto ptr = integers.begin(); //pointer to smallest element
while(ptr != integers.end()){
primes.push_back(*ptr);
integers.erase(std::remove_if(integers.begin(), integers.end(), [=](int x){return x%*ptr==0;}), integers.end());
ptr = integers.begin();
}
return primes;
}
int main() {
auto v = primesBelow(100);
printVector(v);
return 0;
}
值得注意的是,后一个程序正确返回所有素数,但也返回 4。我计算出后一个程序将 2 添加到素数列表中,然后添加 3 并删除 3 的倍数,然后添加 4 并删除倍数4 等。但重要的是没有删除 2 的倍数。
为什么后一个程序有这个错误,当我简单地p
将while
循环中的(等于*ptr
)替换为*ptr
?我会这样认为ptr
并且在循环*ptr
的每次迭代中都不会改变while
(当然,直到循环的最后一行),但显然它们会改变。