- 求解2-n范围内的所有素数
- 一般法:
- 厄尔多累法:
原理:从i=2开始找到当前最小的数i,然后删除2i,3i,4i....
example:i=2 delet 2i 3i 4i...(ki<=n)非素数删除 4 6 8 ....
i=3 delet 3i 4i 5i...
i=4......
剩下的数即为素数
不足:存在重复删除
- 线性法:
原理:每个合数只删除一次
/*一个素数可以分解为一个合数*素数
*其中的合数又可以分解为另外的一对合数*素数
*于是得到一个最大合数*最小素数
*算法中合数只被最小素数除去,避免重复删除
*/
使用java编程:
package prime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Prime {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 给出范围找出所有的素数
Integer M=10000000;
computeTimeSimple(M);//10,0000-16 100,0000-219 1000,0000-4919
computeTimeEras(M);//厄拉多塞法,当前最小值i(i=2~m)删除i*j(j=2,3,k,i*j<m),100,0000-94 1000,0000-1723
computeTimeLine(M);//线性法,10000000-141
}
public static void computeTimeSimple(Integer m) {
double timeSimple1=System.currentTimeMillis();
List<Integer> primeSimple=getPrimeSimple(m);
double timeSimple2=System.currentTimeMillis();
//output(primeSimple);
System.out.println(timeSimple2-timeSimple1);
}
public static void computeTimeEras(Integer m) {
double timeSimple1=System.currentTimeMillis();
List<Integer> primeSimple=getPrimeEras(m);
double timeSimple2=System.currentTimeMillis();
//output(primeSimple);
System.out.println(timeSimple2-timeSimple1);
}
public static void computeTimeLine(Integer m) {
double timeSimple1=System.currentTimeMillis();
List<Integer> primeSimple=getPrimeLine(m);
double timeSimple2=System.currentTimeMillis();
//output(primeSimple);
System.out.println(timeSimple2-timeSimple1);
}
//素数输出
public static void output(List<Integer> prime) {
int count=1;
for(Integer i:prime) {
System.out.print(i+" ");
count++;
if(count%10==0)
System.out.println("");
}
}
//最简单的找素数
public static List<Integer> getPrimeSimple(Integer m) {
List<Integer> prime = new ArrayList<Integer>();
for(int i=2;i<=m;i++) {
int j;
for(j=2;j*j<=i;j++) {
if(i%j==0)
break;
}
if(j*j>i) prime.add(i);
}
return prime;
}
public static List<Integer> getPrimeEras(Integer m){
List<Integer> prime = new ArrayList<Integer>();
Boolean isPrime[]=new Boolean[m+1];
Arrays.fill(isPrime,true);
for(int i=2;i<=m;i++) {
if(isPrime[i]) {
prime.add(i);
}
for(int j=2;j*i<m;j++)
isPrime[j*i]=false;
}
return prime;
}
/*一个合数可以分解为一个合数*素数
*其中的合数又可以分解为另外的一对合数*素数
*于是得到一个最大合数*最小素数
*算法中合数只被最小素数除去,避免重复删除
*/
public static List<Integer> getPrimeLine(Integer m){
List<Integer> prime=new ArrayList<Integer>();
Boolean[] isPrime=new Boolean[m+1];
Arrays.fill(isPrime, true);
for(int i=2;i<=m;i++) {
if(isPrime[i]) {
prime.add(i);
}
for(int j=0;j<prime.size()&i*prime.get(j)<=m;j++) {
isPrime[i*prime.get(j)]=false;
if(i%prime.get(j)==0)
/*如果i能整除prime[j],则i的倍数(n=k*i)能够分解为prime[j]的倍数,
*则删除n使用最小素数prime[j],即使用i'=(k*i)去删除
*/
break;
}
}
return prime;
}
}