zoukankan      html  css  js  c++  java
  • 素数判断

    介绍

        素数又称质数,既只能被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(n*log(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的值。


     

  • 相关阅读:
    cnblog项目--20190309
    django js引入失效问题
    Python老男孩 day16 函数(六) 匿名函数
    Python老男孩 day16 函数(五) 函数的作用域
    Python老男孩 day15 函数(四) 递归
    Python老男孩 day15 函数(三) 前向引用之'函数即变量'
    Python老男孩 day15 函数(二) 局部变量与全局变量
    Python老男孩 day14 函数(一)
    Python老男孩 day14 字符串格式化
    Python老男孩 day14 集合
  • 原文地址:https://www.cnblogs.com/lqc1002000/p/2535334.html
Copyright © 2011-2022 走看看