Eratosthenes筛选
素数 大于一的数中 只能被1和自身整除的数
一般情况 查找某个区间内的素数M 就是那这个数 去和在[2,M-1]; 逐个做除 发现能被整除 说明不是素数 否则表面是素数
这样 当数据量很大的时候 效率显然是低下的
所以这里的Eratosthenes 算法就是一种高效的找出某个区间内所有素数的方法
先看几个对比结果
讲讲这个算法的原理吧
先将这个区间内的所有数MAX 全部认为是素数
int [] prime=new int[MAX]; 默认值是0;
然后分析 能被2整除的肯定不是素数 这样就将这个区间的数 减少了一半 2是素数
剩余的数 无非就是 3 5 7 11 13 。。。。全是素数哈
你会想到 3*3=9 不是素数
5*5
7*7 都不是
所以 那些素数的倍数全不是素数
这样 100区间的话 最大的素数平方就是<100 最大的素数平方根<10
总之一句话 就是找出 区间内的所有能被整除的数 其余的就是素数
再有就是 在判断一个数是否是素数的时候 你只要分析到这个数的开根号
比如 100 你只需要比较 能否被 2 3 4 5 6 7 8 9 10整除就行 也就是 <=根号100 就行
这是为什么是根号的原因
一个数n如果不是素数那么一定存在若干因子(不少于2个), 假设最小的因子是p, 那么p*p <= n 所以p < 根号n
上代码
/**
* 倍数肯定不是素数
* 100为例子 偶数
*素数的倍数 10*10=100
* 所以小于10的素数 3 5 7 9 都是 再把他们的倍数小于MAX剔除 剩余的就是素数
* @author Deamon
*
*/
public class EratosthenesDemo {
public static final double MAX=1000001;
public static void main(String [] args){
long start=System.currentTimeMillis();
fun1();
long end=System.currentTimeMillis();
System.out.println("Eratosthenes 耗时 : "+(end-start));
long start1=System.currentTimeMillis();
fun2();
long end1=System.currentTimeMillis();
System.out.println("普通 耗时 : "+(end1-start1));
}
/**
* 普通算法
*/
private static void fun2() {
int sum=(int) (MAX-1);
for(int i=2 ; i<MAX ; i++){
for(int j=2 ; j<i ; j++){
if(i%j==0){
sum--;
break;
}
}
}
System.out.println("sum "+(sum-1));
}
/**
* Eratosthenes算法
*/
private static void fun1() {
int twin=-1;
int [] primes=new int[(int) MAX]; //默认是0 都是素数
int max=(int) Math.sqrt(MAX);
for(int i=2; i<=max ; i++){
if(primes[i]==0){ //一开始都是素数
for(int j=2*i ; j<MAX ; j++){ //拿每个数 去区间整除 找到就改变标志
if(primes[j]==1)continue;
if(j%i==0){
primes[j]=1;
}
}
}
}
int sum=0;
int t=0;
for(int i=2 ; i<MAX ; i++){
if(primes[i]==0){ //是素数
sum++;
if(i-2==twin){ //孪生素数
//System.out.println("<"+twin+","+i+">");
t++;
}
twin=i;
}
}
System.out.println(((int)(MAX)-1)+" 内总共 : "+sum+"个素数 "+t+"个孪生素数");
}
}