模板编程 实例2 素数判定

来源:互联网 发布:门店经营数据 编辑:程序博客网 时间:2024/06/05 11:25

原理

最基本的素数判断算法,伪代码如下:

function IsPrime(n)

if n == 1 then return false

if n == 2 then return true

for each m from 2

    if m * m > n then return true

    if n mod m = 0 then return false

    m := m + 1

复杂度为O(sqrt(n))的算法,主要的逻辑为循环。

模板元编程是以递归的逻辑形式来实现循环算法;

因此必须先明确两件事:有几个变量参与,以及循环的终止条件是什么。这个算法显然有2个变量参与运算:一个是n,另一个是m。我们令m2开始递增,直到达到循环终止条件。

基本框架

template<uint n, uint m>struct TEST{
          const static uint r = TEST<n, nextM>::r; //nextM为下一个M,暂不实现。在这里用递归结构代替了循环
};
template<uint n>struct ISPRIME{
          const static uint r = TEST<n, 2>::r; //从2开始,依次判断每一个可能的m取值,判断代码暂未实现。
};
template<>struct ISPRIME<1>{ //对于算法不能计算的特殊值1,判断为0
          const static uint r = 0;
};
template<>struct ISPRIME<2>{ //对于算法不能计算的特殊值2,判断为1
          const static uint r = 1;
};

循环的终止条件是m的平方大于n或可以整除n

当满足终止条件时,向模板参数传递一个特殊值,并在偏特化中处理这个值,那么递归逻辑就终止了。而判断是否满足终止条件,则需进行逻辑和算术运算。

改写后的框架

template<uint n, uint m>struct TEST{
       // if (n % m == 0) n = 0;
       // if (m * m > n) m = 0; else ++m;
          const static uint r = TEST<n, m>::r; //上面两行代码不能写在此处,仅说明逻辑。实际的语法下文再做介绍
};
template<uint m>struct TEST<0, m>{ //n为0的情况
          const static uint r = 0; //即在非特化的模板代码中,n可以被m整除,因此n被赋值为0,故为合数
};
template<uint n>struct TEST<n, 0>{ //m为0的情况
          const static uint r = 1; //即在非特化的模板代码中,m * m > n,因此n不能被任何比它小的数整除,故为素数
};
template<uint n>struct ISPRIME{
          const static uint r = TEST<n, 2>::r; //从2开始,依次判断每一个可能的m取值,判断代码暂未实现。
};
template<>struct ISPRIME<1>{ //对于算法不能计算的特殊值1,判断为0
          const static uint r = 0;
};
template<>struct ISPRIME<2>{ //对于算法不能计算的特殊值2,判断为1
          const static uint r = 1;
};

实现

只要用模板的参数推导实现取模的算术运算和上面框架中的两个逻辑判断即可

#include <iostream>
typedef unsigned int uint;
 
template<uint n, uint m>struct NEXTN{
         const static uint r = ((n % m != 0) * n);
};
 
template<uint n, uint m>struct NEXTM{
         const static uint r = (m * m <= n ? (m + 1) : 0);
};
 
template<uint n, uint m>struct TEST{
          const static uint r = TEST<NEXTN<n, m>::r, NEXTM<n, m>::r>::r;
};
 
template<uint m>struct TEST<0, m>{
          const static uint r = 0;
};
 
template<uint n>struct TEST<n, 0>{
          const static uint r = 1;
};
 
template<uint n>struct ISPRIME{
          const static uint r = TEST<n, 2>::r;
};
 
template<>struct ISPRIME<1>{
          const static uint r = 0;
};
 
template<>struct ISPRIME<2>{
          const static uint r = 1;
};
 
int main()
{
          int primes[] = {
                    ISPRIME<1>::r, ISPRIME<2>::r, ISPRIME<3>::r, ISPRIME<4>::r,
                    ISPRIME<5>::r, ISPRIME<6>::r, ISPRIME<7>::r, ISPRIME<8>::r,
                    ISPRIME<9>::r, ISPRIME<10>::r, ISPRIME<11>::r, ISPRIME<12>::r,
                    ISPRIME<13>::r, ISPRIME<14>::r, ISPRIME<15>::r, ISPRIME<16>::r,
          };
          for (int i = 0; i < sizeof(primes) / sizeof(primes[0]); ++i)
                    std::cout << i + 1 << (primes[i] ? " YES" : " NO") <<std::endl;
          return 0;
}
另一实现参考酷壳的博文:http://coolshell.cn/articles/3738.html#more-3738

 

0 0
原创粉丝点击