java筛选法_埃拉托色尼筛选法的Java实现及其原理

Greeting!

今天记录一下如何用埃拉托色尼筛选法实现输出小于某个数n的所有质数,大家都知道质数是除了自己和1之外的所有数整除的数。最粗暴的实现方法就是用两个for循环,在最里层进行取余操作,如果取余为0则不是质数。除此之外,还可以用一种叫埃拉托色尼筛选法(the Sieve of Eratosthenes)的办法,节省内存和运算时间。

埃拉托色尼筛选法的原理

(1)先把1删除(现今数学界1既不是质数也不是合数)

(2)读取队列中当前最小的数2,然后把2的倍数删去

(3)读取队列中当前最小的数3,然后把3的倍数删去

(4)读取队列中当前最小的数5,然后把5的倍数删去

(5)读取队列中当前最小的数7,然后把7的倍数删去

(6)如上所述直到需求的范围内所有的数均删除,剩下的就是质数图片来自百度百科

实现代码

代码由java语言实现,源代码来自 CS 61B (2014 Spring):

public static void printPrimes(int n) {

boolean[] prime = new boolean[n + 1]; // Numbered 0...n.

int i;

for (i = 2; i <= n; i++) {

prime[i] = true;

}

for (int divisor = 2; divisor * divisor <= n; divisor++) {

if (prime[divisor]) {

for (i = 2 * divisor; i <= n; i = i + divisor) {

prime[i] = false; // i is divisible by divisor.

}

}

}

for (i = 2; i <= n; i++) { //print the prime

if (prime[i]) {

System.out.print(" " + i);

}

}

}

代码原理分析这套code的特点在于,创造性地建立了大小为n+1的,bool类型的char数组。

依据char的序号作为筛选质数的作为循环的数本体(从0到n),然后根据对应的char数组里面的bool类型来判断是否为质数。True为是质数,False为不是质数。

注意1:为什么要n+1个数组单位?因为在数组中,序号从0开始计数,所以我们要将数字大小定为n,数组的大小就必须为n+1。(在这里,序号0和1都是没有必要考虑的,原因见原理部分)在第一个循环中,我们假定所有的char数组暂时都为true(即0到n都为质数)。

利用iteration,将所有队列中最小的数(2,3,5,7,11….)的倍数给删去,即下图表格所显示的值都不是质数,所以标为false。

注意2:可以看出这里的divisor为质数从小到大一直到

equation?tex=%5Csqrt%7Bn%7D (后面说明原因),那么如何确定divisor呢?我们根据divisor为质数,可知某质数作为char的序号对应的bool类型为True。可使用if语句:

if (prime[divisor])

如果满足True,则进行下面的循环:

for (i = 2 * divisor; i <= n; i = i + divisor){

prime[i] = false;

}

例如,这里的4所对应的布尔数组已经在第一次循环中(2×2)被标为了false,因此只有这个char[]为true,才进行iteration,因此选出了队列中当前最小的数。作者用Excel画的渣图

注意3:为什么divisor只要到

equation?tex=%5Csqrt%7Bn%7D 呢?我们看到图中标同样颜色的框,其实是重复的,事实上我们如果去除重复的话,表中的信息呈现一个倒三角形状。2从2×2开始,3从3×3开始,5从5×5开始等等,类似于我们小时候背的乘法口诀表。所以当divisor为

equation?tex=%5Csqrt%7Bn%7D 及附近时,要从

equation?tex=%5Csqrt%7Bn%7D 的平方开始,我们要求n以内的质数,再往上就没意义了。在代码段的最后一段中,剩下位置对应的数就是质数,因为在上一个操作中没有被删掉。

利用循环输出标记仍为true的char所对应的位置序号。

最终,我们就可以在屏幕中输出想要的n以内质数啦!

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页