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毫秒

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章