小白初学,还请大佬多多指教。 质数概念 质数即素数,是只能被1和它本身整除的自然数。
相比于遍历奇数偶数来说,遍历质数的难点在于一次循环不能确定一个数是不是质数,必须经过嵌套循环完成之后才可以确定,因此引入一个布尔型变量isFlag,用来标识遍历的结果状态。其中如果把isFlag的声明放在一层循环以内,这样虽然可以简化几行代码,但是过多地消耗了内存,有点得不偿失。 这种方式可以实现遍历,但效率极低。
算法二: class PrimeNumberTest{ public static void main(String[] args){ long start = System.currentTimeMillis(); boolean isFlag = true;//标识i是否被j除尽过,一旦除尽,修改其值 for(int i=2; i<=100000; i++){//遍历100000以内的自然数 //boolean isFlag = true;//标识i是否被j除尽过,一旦除尽,修改其值 for(int j=2; j<i; j++){//j:被i去除 if(i%j == 0){//i被j除尽 isFlag = false; break;//优化一:只对本身非质数的自然数是有效的。只要有一个被除尽就不是质数了,就不需要往下执行了 } } if(isFlag){ //System.out.println(i); } //重置isFlag isFlag = true; } long end = System.currentTimeMillis(); System.out.println("程序执行时间:" + (end - start)); } }算法二对算法一进行了第一步优化,当判定一个数是质数时,做两个工作,一是修改结果状态标识,二是终止内层循环,这样可以大大减少遍历次数。
算法三: class PrimeNumberTest{ public static void main(String[] args){ long start = System.currentTimeMillis(); boolean isFlag = true;//标识i是否被j除尽过,一旦除尽,修改其值 for(int i=2; i<=100000; i++){//遍历100000以内的自然数 //boolean isFlag = true;//标识i是否被j除尽过,一旦除尽,修改其值 for(int j=2; j<=Math.sqrt(i); j++){//j:被i去除 优化二 if(i%j == 0){//i被j除尽 isFlag = false; break;//优化一:只对本身非质数的自然数是有效的。只要有一个被除尽就不是质数了,就不需要往下执行了 } } if(isFlag){ System.out.println(i); } //重置isFlag isFlag = true; } long end = System.currentTimeMillis(); System.out.println("程序执行时间:" + (end - start)); } }该算法使用Math.sqrt()方法,这个方法用来求解一个数的平方根,我们都知道,一个数等于它的平方根的乘积,如上图: i = Math.sqrt(i) * Math.sqrt(i) 假设 y 小于 Math.sqrt(i) ,如果 i = x*y , 那么 x 一定大于 Math.sqrt(i) 。 当我们循环遍历时,只需要遍历到 Math.sqrt(i) 即可,因为我们从2开始遍历时,到 Math.sqrt(i) ,如果这个数不是质数,在2到 Math.sqrt(i) 这个区间内一定存在一个数 y 使得 i = x*y ,这样就能断定这时的 i 一定不是质数,因为 y 既不是1也不是i。 通过这种算法上的优化,可以大大提高代码的执行效率。
算法四: class PrimeNumberTest{ public static void main(String[] args){ long start = System.currentTimeMillis(); lable:for(int i=2; i<=100000; i++){//遍历100000以内的自然数 //优化二:对本身是质数的自然数是有效的。 for(int j=2; j<=Math.sqrt(i); j++){//j:被i去除 if(i%j == 0){//i被j除尽 continue lable;//终止指定标签的for循环的本次循环操作 } } //凡是能执行到这个步骤的,一定是质数,因为非质数全都被终止当次的循环操作了 System.out.println(i); } long end = System.currentTimeMillis(); System.out.println("程序执行时间:" + (end - start)); } }进一步对算法三进行了代码优化,省去了结果状态标识的定义,使用continue关键字并指定for循环标签,终止指定标签的for循环的当次操作。