素数计算---改良版埃氏筛选和欧拉筛选
2016-07-11 16:16
441 查看
埃氏筛选:
例如要找不超过100的所有素数。
需要建立一个大小为100加1个的布尔数组,称为isPrime。
已知0和1不是素数,所以,先找到第一个素数2,那么将其标记为素数。
isPrime[2] = true;
那么2的倍数肯定不是素数,使用建立的布尔数组对它们进行标记
isPrime[2*2] = false;
isPrimer[2*3] = false;
isPrimer[2*n] = false;
当2*n>100时,停止标记。
找第二个素数B,素数B的倍数肯定也不是素数,同样对它们进行标记。
缺陷很明显,会对一些数重复进行标记。
如2和5都是素数,2和5的倍数都有10,20,30,40,50
这些都会重复标记,造成了极大的浪费。
所以有了以下的改良方法,照搬曾加的。
例如要找不超过100的所有素数。
需要建立一个大小为100加1个的布尔数组,称为isPrime。
已知0和1不是素数,所以,先找到第一个素数2,那么将其标记为素数。
isPrime[2] = true;
那么2的倍数肯定不是素数,使用建立的布尔数组对它们进行标记
isPrime[2*2] = false;
isPrimer[2*3] = false;
isPrimer[2*n] = false;
当2*n>100时,停止标记。
找第二个素数B,素数B的倍数肯定也不是素数,同样对它们进行标记。
缺陷很明显,会对一些数重复进行标记。
如2和5都是素数,2和5的倍数都有10,20,30,40,50
这些都会重复标记,造成了极大的浪费。
所以有了以下的改良方法,照搬曾加的。
/** * Created by xu-cat on 2016/7/11. * 使用筛选法,计算出N个以内的素数 * 作者:曾加 * 链接:https://www.zhihu.com/question/24942373/answer/29599552 */ class Prime{ public static int calculateNumber(int Nmax){ boolean[] isPrime=new boolean[Nmax+1]; //假定所有奇数为素数,即首先筛掉偶数 for(int i=3;i<=Nmax;i+=2) isPrime[i]=true; isPrime[2]=true; for(int i=3;i<=Math.sqrt(Nmax);i+=2){ if(isPrime[i]==true){ // 偶数是不需要判断的 // j+=2*i中i必定是奇数,那么i*2之后必定是偶数 // 奇数+偶数=奇数,所以j一直是奇数,从而排除了标记偶数 for(int j=i*i;j<=Nmax;j+=2*i) isPrime[j]=false; } } int primeNum=0; for(int i=1;i<=Nmax;i++){ if(isPrime[i]==true) { primeNum++; } } return primeNum; } public static int calculateNumber1(int Nmax) { boolean[] isPrime = new boolean[Nmax + 1]; //存着素数 int[] prime = new int[Nmax / 10]; //筛选偶数,只留下奇数 for (int i = 3; i <= Nmax; i += 2) isPrime[i] = true; //2先处理掉 isPrime[2] = true; prime[0] = 2; int totalPrimes = 1; for (int i = 3; i <= Nmax; i += 2) { if (isPrime[i]) prime[totalPrimes++] = i; for (int j = 1; i * prime[j] <= Nmax && j < totalPrimes; j++){ isPrime[i * prime[j]] = false; //看不懂,先放着,再见! if(i % prime[j] == 0) break; } } return totalPrimes; } public static void main(String[] args){ ooxx(20000000, true); ooxx(20000000, false); } public static void ooxx(int Nmax, boolean choose) { double startTime=System.currentTimeMillis(); int primeNum; if (choose) { //改良版埃氏筛法 primeNum=Prime.calculateNumber(Nmax); } else { //选择欧拉晒法 primeNum=Prime.calculateNumber1(Nmax); } double timeSpent=(System.currentTimeMillis()-startTime)/1000; System.out.println("The prime numbers from 1 to "+Nmax+" is "+primeNum); System.out.println("Time spent : "+timeSpent+" s"); } }
改良版 Time spent : 0.294 s 欧拉版 Time spent : 0.29 s
END
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树