今天有位朋友去面試,一道題是“寫段代碼驗證哥德巴哈猜想”,覺得很有意思,因為其中涉及到剛接觸電腦時搞過的求素數演算法,在記憶中,為了提高效率(用空間換時間),應該是保留已求得的素數,然後在判斷N的時候,只需用N去依次試除所有不大於N平方根的已知質數,而勿需遍曆小於N的所有(奇)數。按上述思路編製的Primes類如下,可做為“驗證哥德巴哈猜想”的輔助類(因為這個需求,所以該類的generate()方法可以按需要計算出所需的素數)。這個求素數的演算法速度很不錯,在我賽揚2.0的機器上,大約在1.5秒就可以算出所有小於一百萬的素數,共78,498個。
#pragma once
#include <vector>
#include <ostream> // for ostream & operator << ()
#include <cmath> // for sqrt()
class Primes {
public:
Primes() {
primes_.push_back(2);
primes_.push_back(3);
}
//產生不小於maxValue的所有質數
void generate(int maxValue) {
if (maxValue <= getMaxPrime())
return;
for (int v=getMaxPrime()+2; v<=maxValue; v+=2) {
int sqrtV = static_cast<int>(sqrt(static_cast<double>(v)));
bool isPrime = true;
for (size_t i=0; i<primes_.size() && primes_[i]<=sqrtV; ++i) {
if (0==(v % primes_[i])) {
isPrime = false;
break;
}
}
if (isPrime)
primes_.push_back(v);
}
}
//取已產生的最大質數
int getMaxPrime() const { return primes_[primes_.size()-1]; }
//取已產生的質數個數
size_t getCount() const { return primes_.size(); }
//取已產生質數中的指定序號項的質數
int operator[](int index) const { return primes_[index]; }
//判斷給定數是不是質數
bool isPrime(int value) const {
if (value<primes_[0] || (value!=2 && 0==(value % 2)) || value>getMaxPrime())
return false;
//用二分法在已知質數中尋找
size_t low=0, high=primes_.size()-1;
while (low<=high) {
size_t midd = (low + high) / 2;
int middPrime = getValue(midd);
if (value==middPrime)
return true;
if (value<middPrime)
high = midd - 1;
else
low = midd + 1;
}
return false;
}
//測試用,將產生的所有質數輸出到流中
friend std::ostream & operator << (std::ostream & os, const Primes & right) {
for (size_t i=0; i<right.primes_.size(); ++i)
os << right.primes_[i] << "/t";
os << std::endl;
return os;
}
private:
std::vector<int> primes_;
};
網上有段FLASH示範二分尋找,很有意思: