【发布时间】:2021-08-21 20:43:48
【问题描述】:
我一直在尝试创建一个 C++ 程序来查找某个整数 n 下的所有素数,使用 Sieve of Eratosthenes algorithm,如下所示:
-
创建一个从 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 的倍数。
当我简单地将while 循环(等于*ptr)中的p 替换为*ptr 时,为什么后一个程序会有这个错误?我原以为ptr 和*ptr 在while 循环的每次迭代中都不会改变(当然,直到循环的最后一行),但显然它们会改变。
【问题讨论】: