为了展现编译期数值计算的强大能力,下面是一个更复杂的计算:最大公约数(Greatest Common Divisor,GCD)和最小公倍数(Lowest Common Multiple,LCM),经典的辗转相除算法:
int lcm(int a, int b){
int r, lcm=a*b;
while(r=a%b) { a = b; b = r; } // 因为用可变的存储,不能写成 a=b; b=a%b;
return lcm/b;
}
// 递归函数版本
int gcd_r(int a, int b) { return b==0 ? a : gcd_r(b, a%b); } // 简洁
int lcm_r(int a, int b) { return a * b / gcd_r(a,b); }
// 模板版本
template<int a, int b>
class lcm_T{
template<typename stat>
class cond { public: enum{ ret=(stat::div!=0) }; };
template<int a, int b>
class stat { public: typedef stat<b, a%b> Next; enum{ div=a%b, ret=b }; };
static const int gcd = WHILE_<cond, stat<a,b>>::reType::ret;
public:
static const int ret = a * b / gcd;
};
// 递归模板版本
template<int a, int b>
class lcm_T_r{
template<int a, int b> class gcd { public: enum{ ret = gcd<b,a%b>::ret }; };
template<int a> class gcd<a, 0> { public: enum{ ret = a }; };
public:
static const int ret = a * b / gcd<a,b>::ret;
};
int main() {
std::cout << lcm(100, 36) << '\n';
std::cout << lcm_r(100, 36) << '\n';
std::cout << lcm_T<100, 36>::ret << '\n';
std::cout << lcm_T_r<100, 36>::ret << '\n';
std::cin.get(); return 0;
}
|