【练习总结】题目:筛法遍历素数(Java)
初学Java,学到流程控制的循环,有个练习题是暴力遍历素数。
因为看过av32186751,知道有个筛法,就想试试。
又受到线性筛法(一)--素数筛法(一) - nerd呱呱 - 博客园中,的这段启发,就有了下面的代码。
引用文字:
我们先定义一个数组来存100000以内数是否的素数,下标表示数,数组的值1表示是素数,0表示不是素数。
我们可以换个角度思考,要找素数,其实只要把不是素数的排除就可以了。
代码:
1 import java.util.Scanner; 2 /** 3 * ShaiFa_Prime__Basic 4 * @author HmLy.0000 5 * * * * * * * * * * * * * 6 */ 7 public class ShaiFa_Prime__Basic { 8 9 /** 10 * 这边,直接用i 来表示"thisNumber[i]" ... 11 */ 12 public static void main(String[] args) { 13 System.out.println(); 14 Scanner scn = new Scanner(System.in); 15 System.out.println("# 【这是个筛法遍历素数的工具】"); 16 17 System.out.println("# --> 目前还不能输入同一个数。"); 18 System.out.println("# "); 19 System.out.println("# ==== -- ==== -- ==== -- ==== "); 20 System.out.println("# 请指定遍历素数区间范围 : "); 21 System.out.println("# ---- --- --- ---- --- -- ---- -- -"); 22 23 24 25 boolean[] isPrime_AHA; 26 int numberArr_i_OP, numberArr_i_ED; 27 28 29 30 31 32 while (true) { 33 System.out.print ("# 指定区间边界<1>, 最少是 2 : | "); 34 numberArr_i_OP = scn.nextInt(); 35 if (numberArr_i_OP >= 2) { 36 break; 37 } else { 38 System.out.println("# [ERR!!] - === 您输入的值非法,请重新输入!!===="); 39 }//if-else_to_break 40 }//whileTrue 41 42 43 44 while (true) { 45 System.out.print ("# 指定区间边界<1>, 最少是 2 : | "); 46 numberArr_i_ED = scn.nextInt(); 47 if (numberArr_i_ED >= 2) { 48 break; 49 } else { 50 System.out.println("# [ERR!!] - === 您输入的值非法,请重新输入!!===="); 51 }//if-else_to_break 52 }//whileTrue 53 54 55 56 57 58 if (numberArr_i_ED < numberArr_i_OP){ 59 int temp = numberArr_i_ED; 60 numberArr_i_ED = numberArr_i_OP; 61 numberArr_i_OP = temp; 62 }//交换位置 63 64 65 66 67 68 69 70 71 //int largePrim = (numberArr_ED - numberArr_OP + 1); 72 isPrime_AHA = new boolean[numberArr_i_ED + 1]; 73 74 75 for (int i = 0; i <= numberArr_i_ED; i++) { 76 isPrime_AHA[i] = true; 77 } 78 79 isPrime_AHA[0]= false; 80 isPrime_AHA[1]= false;//先不想办法省掉它俩。。 81 82 int nnn_i__tst; 83 for (int i = 2; i <= numberArr_i_ED; i++) { 84 85 if(isPrime_AHA[i]){ 86 for (nnn_i__tst = i*2; nnn_i__tst <= numberArr_i_ED; nnn_i__tst++) { 87 if(nnn_i__tst% i== 0){ 88 isPrime_AHA[nnn_i__tst] = false; 89 } 90 }//检查大于2的数是否是其倍数,是,就false。从2 的两倍开始检查 - 因为其前面的必定不是倍数。。。。 91 }//对所有还没false的进行操作。 92 }//不光检查2。所有还没false的都得检查。 93 94 95 96 97 98 //打印 99 System.out.println("# ---- --- --- ---- --- -- ---- -- -"); 100 System.out.println("# 区间为 : |["+ numberArr_i_OP +", "+ numberArr_i_ED +"]"); 101 System.out.println("# 区间长度 : |["+ (numberArr_i_ED +1 - numberArr_i_OP) +"]"); 102 System.out.println("# ---- ---- ---- ---- | "); 103 int primeCunt = 0; 104 for (int i = numberArr_i_OP; i <= numberArr_i_ED; i++) { 105 if (isPrime_AHA[i]) { 106 primeCunt++; 107 } 108 }//数数 109 System.out.println("# 区间中素数个数 : | "+ primeCunt); 110 System.out.println("# -- - - ---- --"); 111 112 113 for (int i = numberArr_i_OP; i <= numberArr_i_ED; i++) { 114 if (isPrime_AHA[i]) { 115 System.out.println("# 区间中的素数 : | "+ i); 116 } 117 }//输出 118 System.out.println("# ---- --- --- ---- --- -- ---- -- -"); 119 }//main 120 } 121 /** 122 * 受到了查到的筛法的启发。 123 * * * * * * * * * * * * * 124 * 先前尝试再来个数组,就不用让 i 为 0 和 1 125 * 的部分被白费,但直接整晕了... 上面这个先简单来,成功了。 126 */
为了这个专门预习了数组。
一开始独立写代码,想在开始就不让程序浪费一开始的0和1两个下标,就又弄了一个数组又定义了一堆新变量,然后自己也晕在里面了。。。索性就不管这个,然后就成了。
- - - - - -
对了,一开始的时候弄得那个全是bug的代码似乎还一口气加上了指定遍历开头的功能……
这个的话,是从2开始遍历,只是取值可以设定区间而已,区间只是帮助截取显示的部分,选择小区间并不见得就会减少程序运算量。。。。
- - - - - -
而且,遍历下标倍数的时候上面的代码也弄复杂了。
甭判断这个 % 那个是不是 0 ,直接从 2 到 n 操作一遍 isPrime[i*j] = false ,就成了。。。。