为了展现编译期数值计算的强大能力,下面是一个更复杂的计算:最大公约数(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;
- }
|