一共四个代码段
首先是最基础的方法,因为方法效率太差,所以就用10W先进行测试,最终优化的程序将运行100W以内的所有质数,因为程序和人的思维计算能力不一样所以中间会有一个插曲,第三个和第四个代码的时候会说明.
第一个代码段是最基础的算法:输出10W以内的质数的数量和时间(同时本代码的结果用于对照优化后代码的输出正确性)
程序运行时间:7441ms
质数个数:9592
package cn.king;
public class test1 {
public static void main(String[] args) {
int k =0;
long startTime = System.currentTimeMillis() ; //获取开始时间
for(int i=2;i<=100000;i++) {
boolean t = true;
for(int j=2;j<i;j++) {
if(i%j==0) {
t=false;
}
}
if(t==true) {
System.out.println(i);
k++;
}
}
long endTime = System.currentTimeMillis() ; //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
System.out.println("质数个数:"+k);
}
}
第二个优化后的代码,本次优化在时间复杂度上都是o(n),所以在高数量的时候效果会差很多,后面会在100W以内质数时对比,经过对比,可以发现在个数上没有任何问题,本次优化成功.时间上与少了很多
程序运行时间:384ms
质数个数:9592
package cn.king;
public class test2 {
public static void main(String[] args) {
int k =0;
long startTime = System.currentTimeMillis() ; //获取开始时间
for(int i=2;i<=100000;i++) {
boolean t = true;
for(int j=2;j<=i/2;j++) {
if(i%j==0) {
t=false;
break;
}
}
if(t==true) {
System.out.println(i);
k++;
}
}
long endTime = System.currentTimeMillis() ; //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
System.out.println("质数个数:"+k);
}
}
接下来第三种优化,也是最推荐的优化,(注:Math.sqrt(i)是开根的意思) 时间复杂度发生了改变,变成了根号n,不过在数据量比较小的时候,比如100的时候,包括第四种在内的效率都会不如第二个,因为在开平方所用的时间会比较长,所以在数据较大的时候会比较好.
和上面对比,个数一致.
程序运行时间:51ms
质数个数:9592
package cn.king;
public class test1 {
public static void main(String[] args) {
boolean t ;
int k =0;
long startTime = System.currentTimeMillis() ; //获取开始时间
for(int i=2;i<=100000;i++) {
t = true;
for(int j=2;j<=(int) Math.sqrt(i);j++) {
if(i%j==0) {
t=false;
break;
}
}
if(t==true) {
System.out.println(i);
k++;
}
}
long endTime =System.currentTimeMillis() ; //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
System.out.println("质数个数:"+k);
}
}
第四种:这一种会涉及一些数学类的知识,是用数据去除以前面的质数,然后再把得到的质数去写入数组,在人脑的计算中,本方法会相对于上面比较简单,但是在机器语言中,因为在处理不同数据和放大时时的效率不同所以本方法的速度会低于第三种,
和上面对比,个数一致.
程序运行时间:136ms
质数个数:9592
package cn.king;
import java.util.Arrays;
public class test3 {
static boolean t;
static int k =0;
static int size=1;
public static void main(String[] args) {
int[] a= {2};
long startTime = System.currentTimeMillis() ;
for(int l=0;l<a.length;l++) {
System.out.println(a[l]);
k++;
}
for(int i=2;i<100000;i++) {
t=true;
for(int j=0;j<size;j++) {
if(i%a[j]==0) {
t=false;
break;
}
}
if(t==true) {
a=Arrays.copyOf(a,++size);
a[size-1]=i;
System.out.println(i);
k++;
}
}
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
System.out.println("质数个数:"+k);
}
}
接下来将要进行100W以内的对比,因为方法一速度过慢,被淘汰出局(石锤工具人)
方法二: 程序运行时间:28846ms 质数个数:78498
方法三: 程序运行时间:601ms 质数个数:78498
方法四: 程序运行时间:5881ms 质数个数:78498
可以发现,此时的时间差距相差很多,方法三和方法二将近50倍的效率差距.如果数据量更大,将差距更多.所以说明了代码优化的必要性.
接下来将要进行1000W以内的对比,因为方法二速度过慢,被淘汰出局(怕跑到地老天荒)
方法三: 程序运行时间:11915ms 质数个数:664579
方法四: 程序运行时间:463325ms 质数个数:664579
可以看出,此时方法三和方法四的效率差距有将近50倍.方法三的效率远高于方法四.
接下来是终极挑战,进行一亿以内的时间和个数,方法四也将被淘汰(怕电脑跑着跑着原地爆炸)
方法三: 一亿以内最后一个质数是 99999989 程序运行时间:333806ms 质数个数:5761455
可以发现用方法三跑一亿以内的质数花费的时间还要快于用方法四跑一千万以内质数的时间.
综上所述,方法三符合王境泽真香定理.