Java实现输出100以内的质数及算法结构优化

  • 输出100以内的所有质数
  • 质数:也叫素数,只能被1和他本身整除的自然数
  • 最小的质数:2

方法一:效率很低

public class PrimeNumber {
    public static void main(String[] args) {
    }
    
    @Test
    public void method1(){
        boolean b = true;
        //遍历100以内的自然数
        for (int i = 2;i<=100;i++){
            //j:被i除
            for (int j=2;j<i;j++){
                if (i % j == 0){    //%是求模运算,即2%10=2,10%2=0,10%3=1。
                    b = false;
                }
            }
            if (b){
                System.out.print(i+" ");
            }
            b = true;
        }
    }
}

输出结果:

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 

实际上,上面的这种方法基本上是效率最低的。但因为100实在是太小了,计算机的运算速度很快就能计算出100以内的质数,所以现在我们不改变算法的结构,把100换成10万试试。

继续方法一:
    @Test
    public void method1(){
        //获取当前时间距离1970-01-01 00:00:00的毫秒数
        long start = System.currentTimeMillis();
        boolean b = true;
        //遍历100以内的自然数
        for (int i = 2;i<=100000;i++){
            //j:被i去除
            for (int j=2;j<i;j++){
                if (i % j == 0){    //%是求模运算,即2%10=2,10%2=0,10%3=1。
                    b = false;
                }
            }
            if (b){
                System.out.print(i+" ");
            }
            b = true;
        }
        //获取当前时间距离1970-01-01 00:00:00的毫秒数
        long end = System.currentTimeMillis();
        System.out.println("\n花费时间:"+(end-start));  //17704毫秒
    }

运行结果:
在这里插入图片描述
用以上这种方法,输出10万以内的质数居然用了 17704毫秒,即17.7秒。在真实开发中。这么慢的速度是绝对不允许的。
所以接下来对这个算法进行优化


方法二:

优化一:使用break更快地跳出循环

    //对方法一进行优化
    @Test
    public void method2(){
        //获取当前时间距离1970-01-01 00:00:00的毫秒数
        long start = System.currentTimeMillis();
        //遍历100以内的自然数
        for (int i = 2;i<=100000;i++){
            boolean b = true;
            for (int j=2;j<i;j++){
                if (i % j == 0){    //%是求模运算,即2%10=2,10%2=0,10%3=1。
                    b = false;
                    break;//优化一:只对本身非质数的自然数是有效的
                }
            }
            if (b){
                System.out.print(i+" ");
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("\n花费时间:"+(end-start));  //优化一后:花费时间 1542ms
    }

这一次,我在最内层的if语句中加入了 break;
这样做的目的是让非质数更快的跳出循环,比如for循环到了100,此时i=100,进入第二个for循环,此时j=2,100%2=0,于是马上就break出了循环

运行结果:
在这里插入图片描述
可以看到,优化过后的速度立马就上来了,用时1542毫秒。


方法三:

既然能对非质数进行优化,那是否可以对质数进行优化呢?当然可以
优化二:对本身是质数的自然数进行优化

    @Test
    public void method3(){
        //获取当前时间距离1970-01-01 00:00:00的毫秒数
        long start = System.currentTimeMillis();
        //遍历100以内的自然数
        for (int i = 2;i<=100000;i++){
            boolean b = true;
            //优化二:对本身是质数的自然数是有效的
            for (int j=2;j<Math.sqrt(i);j++){
                if (i % j == 0){    //%是求模运算,即2%10=2,10%2=0,10%3=1。
                    b = false;
                }
            }
            if (b){
                System.out.print(i+" ");
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("\n花费时间:"+(end-start));  //优化二:208ms
    }

为什么这样优化我就不解释了,大家可以看尚硅谷宋红康老师讲的这一课:http://www.gulixueyuan.com/course/309/task/7787/show

运行结果:
在这里插入图片描述
可以看到,现在运行结果相比优化一又快了,用了208ms。


方法四:

最终优化:把优化一和优化二结合。

    public void method4(){
        //获取当前时间距离1970-01-01 00:00:00的毫秒数
        long start = System.currentTimeMillis();
        //遍历100以内的自然数
        for (int i = 2;i<=100000;i++){
            boolean b = true;
            //优化二:对本身是质数的自然数是有效的
            for (int j=2;j<Math.sqrt(i);j++){
                if (i % j == 0){    //%是求模运算,即2%10=2,10%2=0,10%3=1。
                    b = false;
                    break;//优化一:只对本身非质数的自然数是有效的
                }
            }
            if (b){
                System.out.print(i+" ");
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("\n花费时间:"+(end-start));  //优化一加优化二:71ms
    }

运行结果:
在这里插入图片描述
两种算法优化结合在一起效果不言而喻,输出10万以内的质数仅用了71毫秒

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值