素数简谈

介绍
素数又称质数,既只能被1和它本身除尽的自然数。也就是说素数只有1和它本身两个约数,它只能表示为1和它本身的乘积。

原理
使用一个for循环分别将需要判断的数(number)和2到number-1进行取余运算,如余数为0则表示可以除尽。当number不能被2到number-1的任何一个数除尽的时候,则number为素数,否则则不为素数。

void main()
    {
       int i = 0;
     int a[10] = {5,4,9,8,7,6,0,1,3,2}; // 也可以是用scanf方法得到需要判断的数
     for(i = 0; i < 10; i++)
     {
     if(judgeprime(a[i])) // 调用素数判断函数
     printf("%d是素数. ", a[i]);
     else
     printf("%d不是素数. ", a[i]);
     }
    }

算法1 复杂度O(nlog(n))

#include <iostream>
using namespace std;
  
bool isPrime(int nr)
{
    for (int d = 2; (d * d) < (nr + 1); ++d){
        if (!(nr % d)){
            return false;
        }
     }
    return true;
}
  
int main (int argc, char * const argv[])
{
    for (int i = 0; i < 50; ++i){
        if (isPrime(i)){
            cout << i << endl;
        }
    }
}

算法2 复杂度O(n(log(logn)))采用排除法的方式

示例:打印30以内的质数

一、初始化如下列表。

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
二、把第一个数(2)取出来,去掉所有可以被2整除的数。

2 3 5 7 9 11 13 15 17 19 21 23 25 27 29
三、取第二个数(3),去掉所有可以被 3整除的数。

2 3 5 7 11 13 17 19 23 25 29
四、取第三个数(5),因为4已经被去除了,再去掉所有可以被5整除的数。

2 3 5 7 11 13 17 19 23 29
接下来的数是7,但是7的平方是49,其大于了30,所以我们可以停止计算了。剩下的数就是所有的质数了。

算法3.O(log(n))或是O(1)的时间复杂度

把质数事先就计算好,放在一个文件中,然后在程序启动时(注意是在启动时读这个文件,而不是运行时每调用一次就读一次文件),读取这个文件,然后打印出来就可以了。如果需要查找的化,二分查找或是hash表查找将会获得巨大的性能提升。

算法4

使用编译时而不是运行时

template<int N, int D = N - 1>
struct isPrime {
    enum {
        result = (N % D) && isPrime<N, D-1>::result
    };
};
  
template<int N>
struct isPrime<N, 1> {
    enum {
        result = true
    };
};

于是,通过这个模板,我们可以使用下面的代码来检查是否是质数:

1
2

if (isPrime<3>::result) 
    cout << "Guess what: 3 is a prime!";

下一步,我们需要打出一个区间内的质数,所以,我们需要继续设计我们的print模板。

1
2
3
4
5
6
7
8
9
10
11

template<int N, bool ISPRIME> 
struct printIfPrime { 
    static inline void print() {} 
}; 
  
template <int N> 
struct printIfPrime<N, true> { 
    static inline void print() { 
        std::cout << N << endl; 
    } 
};

从上面的代码中,我们可以看到,我们的第一个实际是什么也没做,而第二个有输出,注意第二个的模板参数中有一个true,其意味着那个质数的判断。于是我们就可以给出下面的代码来尝试着打印出一段区间内的质数:(请不要编译!!因为那会让编译器进入无限循环中,原因是printPrimes会不停地调用自己永不停止)

1
2
3
4
5
6
7
8

template<int N, int MAX> 
struct printPrimes { 
    static inline void print() 
    { 
        printIfPrime<N, isPrime<N>::result>::print(); 
        printPrimes<N + 1, MAX>::print(); 
    } 
};

为了避免这个问题,你需要再加一个模板类,如下所示。这样当N变成MAX的时候,递归就结束了。

1
2
3
4
5
6

template<int N> 
struct printPrimes<N, N> { 
    static inline void print() { 
        printIfPrime<N, isPrime<N>::result>::print(); 
    } 
};

最后,让我们来看看最终的调用:

1
2
3
4
5

int main (int argc, char * const argv[]) 
{ 
    printPrimes<2, 40>::print(); 
    return 0; 
}

这个方法很NB,但是有两个问题:

比较耗编译时间。
不能在运行时输入MAX的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值