java之简单的判断素数算法

来源:互联网 发布:ubuntu 无线网络配置 编辑:程序博客网 时间:2024/03/28 21:21

转载自:http://blog.csdn.net/ylyg050518/article/details/48266999

继续算法之旅。关于素数判定这个问题,也是一个很经典的程序设计题目。

概念:质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除,换句话说就是该数除了1和它本身以外不再有其他的因数,否则称为合数

朴素法

分析:如果要判定一个数自然数n(n>1)是不是素数,从素数定义出发,首先想到的肯定是采用循环,遍历 2至n-1所有值,逐个与n除,判定是否可以整除,如果存在能够整除的情况,则n不为素数。

改进方法:脱离单纯程序实现的角度,你会发现可以改进的地方在于遍历的范围,如果略作思考,你会发现n/2到n-1的值是不用遍历的,因为最小的试探除数是2,大于n/2的数肯定不能被整除。进一步思考,遍历的范围还可以继续缩小,其实只需将遍历的上限设置成n的平方根即可。简单分析,假设 n可以被p整除,结果为q ,即q=n/p,如果p大于n的平方根,q必定小于n的平方根,所以只要测试n的平方根以下的数字即可,这样可以进一步提高运算效率。


以下是代码:

[java] view plain copy
  1. <span style="font-size:14px;">public class Prime {  
  2.     /** 
  3.      * 打印1-100的素数 
  4.      *  
  5.      * @param args 
  6.      */  
  7.     public static void main(String[] args) {  
  8.         for (int i = 1; i <= 100; i++)  
  9.             if (isPrime(i))  
  10.                 System.out.println(i);  
  11.   
  12.     }  
  13.   
  14.     public static boolean isPrime(int num) {  
  15.         if (num == 1)  
  16.             return false;  
  17.         int max = (int) Math.sqrt(num);  
  18.         for (int i = 2; i <= max; i++)  
  19.             if (num % i == 0)  
  20.                 return false;  
  21.         return true;  
  22.     }  
  23. }</span>  

筛数法

  筛数法求素数的基本思想是:把从1开始的、某一范围内的正整数从小到大顺序排列, 1不是素数,首先把它筛掉。剩下的数中选择最小的数是素数,然后去掉它的倍数。依次类推,直到筛子为空时结束。

具体做法如下:
<1> 先将1挖掉(因为1不是素数)。
<2> 用2去除它后面的各个数,把能被2整除的数挖掉,即把2的倍数挖掉。
<3> 用3去除它后面的各数,把3的倍数挖掉。
<4> 分别用4、5…各数作为除数去除这些数以后的各数。(事实上,可以简化,如果需要找1~n范围内素数表,只需进行到除数为n^2(根号n),取其整数即可。例如对1~50,只需进行到将50^2作为除数即可。)

如上算法可表示为:
<1> 挖去1;
<2> 用刚才被挖去的数的下一个数p去除p后面各数,把p的倍数挖掉;
<3> 检查p是否小于n^2的整数部分(如果n=1000, 则检查p<31?),如果是,则返回(2)继续执行,否则就结束;
<4> 纸上剩下的数就是素数。


特别说明:为什么除数的筛选范围只到问题规模N的平方根即可?因为通过分析可以知道,当除数的范围大于这个上限(N的平方根取整)时,所有的要筛选的值都和之前筛选过的重复,继续筛选无效。

代码如下:

[java] view plain copy
  1. /** 
  2.      * 删选法求素数 
  3.      *  
  4.      * @param N 
  5.      */  
  6.     public static void isPrime2(int N) {  
  7.         int[] flags = new int[N + 1];  
  8.         for (int i = 0; i < N + 1; i++)  
  9.             flags[i] = i;  
  10.         flags[1] = 0;// 排除1,1不为素数  
  11.         int max = (int) Math.sqrt(N);// 设定N的除数的范围,小于N的平方根  
  12.         for (int i = 2; i <=max; i++) {  
  13.             for (int j = i + 1; j <= N; j++) {  
  14.                 //筛选,将N的除数的倍数去掉  
  15.                 if (flags[j] != 0 && flags[j] % i == 0) {  
  16.                     flags[j] = 0;  
  17.                 }  
  18.             }  
  19.         }  
  20.         for (int i = 1; i <= N; i++) {  
  21.             if (flags[i] != 0) {  
  22.                 System.out.println(flags[i]);  
  23.             }  
  24.         }  
  25.   
  26.     }  

6N±1法求素数

  任何一个自然数,总可以表示成为如下的形式之一:

  6N,6N+1,6N+2,6N+3,6N+4,6N+5 (N=0,1,2,…)

  显然,当N≥1时,6N,6N+2,6N+3,6N+4都不是素数,只有形如6N+1和6N+5的自然数有可能是素数。所以,除了2和3之外,所有的素数都可以表示成6N±1的形式(N为自然数)。根据上述分析,我们只对形如6 N±1的自然数进行筛选,这样就可以大大减少筛选的次数,从而进一步提高程序的运行效率和速度。

实现思路:可以和朴素法判定单个自然数是否为素数结合起来,利用循环递增获取指定范围具备6 N±1特征的数字,利用朴素法来判定数字是否为素数,打印出结果。

以下是代码

[java] view plain copy
  1. /* 
  2.  * 6N+1法求素数 
  3.  */  
  4.   
  5. public static void isPrime3(int N) {  
  6.     if (N <= 1)  
  7.         System.out.println("此范围无素数");  
  8.     else if (N > 1 && N <= 2)  
  9.         System.out.println(2);  
  10.     else if (N > 2 && N <= 4) {  
  11.         System.out.println(2);  
  12.         System.out.println(3);  
  13.     } else {  
  14.         System.out.println(2);  
  15.         System.out.println(3);  
  16.         int k = 1, pre = 0, next = 0;  
  17.         while (true) {  
  18.             pre = 6 * k - 1;  
  19.             next = 6 * k + 1;  
  20.             if (isPrime1(pre) && pre <= N)  
  21.                 System.out.println(pre);  
  22.             else if (pre > N)  
  23.                 break;  
  24.             if (isPrime1(next) && next <= N)  
  25.                 System.out.println(next);  
  26.             else if (next > N)  
  27.                 break;  
  28.             k++;  
  29.         }  
  30.     }  
  31. }  

特别说明:以上只给出代码样例,并不能保证代码的权威性,加之作者水平有限,难免有不足之处,还望大家多多包涵。


原创粉丝点击