Eratosthenes 筛选素数

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+"个孪生素数");
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值