前几天写的那段代码,其实有很多可以优化的地方,最简单的就是不用遍历整个素数数组,比方说,给定的偶数是100,则只需要从2至97这个素数范围来计算,97以上的素数(如101)就不需要参与计算了。这个思路需要从已知素数中找到最接近给定偶数的素数,又要用到二分法,所以先把二分法提炼成为一个模板类,以供重用:
#pragma once
// T: 容器中项目类型
// CONTAINER: 容器,必须提供[](int)下标取值操作
template<typename T, class CONTAINER>
class BinarySearch {
public:
//搜索,成功返回下标值,失败返回-1
static int execute(
const CONTAINER & container, //容器
int containerSize, //容器中元素总数
const T & t, //要匹配的值
bool extract = true //精确匹配吗?如果为false,则在未找到时返回最接近的下标值
)
{
if (containerSize<=0)
return -1;
int low = 0, high = containerSize - 1, midd = 0;
while (low<=high) {
midd = (low + high) / 2;
const T & middValue = container[midd];
if (t==middValue)
return midd;
if (t<middValue)
high = midd - 1;
else
low = midd + 1;
}
return extract ? -1 : midd;
}
};
接下来,验证算法修改为:
class Goldbach {
public:
bool check(int even, int & prime1, int & prime2) {
if (even<=2 || 0!=(even % 2))
throw std::logic_error("要求大于2的偶数");
//生成不小于even的所有素数
primes_.generate(even);
//找到最接近even的素数
int nearIndex = BinarySearch<int, Primes>::execute(primes_, static_cast<int>(primes_.getCount()), even, false);
//遍历
for (int i=0; i<=nearIndex; ++i) {
for (int j=nearIndex; j>=0; --j) {
if (primes_[i]+primes_[j]==even) {
prime1 = primes_[i];
prime2 = primes_[j];
return true;
}
}
}
return false;
}
const Primes & getPrime(void) const { return primes_; }
private:
Primes primes_;
};