1. 程式人生 > >演算法-----求n以內素數(質數)

演算法-----求n以內素數(質數)

求n以內素數(質數)。


java版

這道題看到一眼就能想到一個for迴圈,對每個數取餘,如果==0,說明能除斷,就不是素數(質數)。

1、如果用上面的方法去做,當n小的時候,沒什麼,當n資料大的時候,效率就是一個問題,做了很多無用判斷。

改進:

1、所有的偶數都不是素數(質數),所以不用對偶數進行判斷取餘。

2、第一個可能想到,大於該數1/2的數都不能整除,(例如:該數100除以50(不包括50)之後的數都不可能整除)

    但是,經規律實驗證明 ,大於該數的二次根的數都不能整除。

CODE:

package com.company;

/**
 * 求100以內素數(質數) 最終方案:不需要迴圈每一次判斷,
 * 1.所有偶數都不是質數
 * 2.所有奇數除以偶數都除不斷,只需要判斷對奇數取餘,減少判斷次數
 * 3.大於該數字二次根的數字 是不能整除的。減少迴圈數字範圍。
 */
public class PrimeNumber {

    private boolean isPrimeNumberFour(int number) {
        double sqrt = Math.sqrt(number); //必須把 Math.sqrt(number) 提前賦值好,要不然放在 sqrt 處,每次比較都會計算一次,影響效能。
        for (int j = 3; j < sqrt; j+=2) {
            if (number % j == 0) return false;
        }
        return true;
    }
    private void methodFour(int number) {
        long start = System.currentTimeMillis();
        if (number>=2) System.out.println("Number:2 Is Prime Number");
        for (int i = 3; i < number; i+=2) {
            if (isPrimeNumberFour(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodFour 花費時間:"+(end-start)+"ms");
    }
    public static void main(String[] args) {
        PrimeNumber primeNumber = new PrimeNumber();
        primeNumber.methodFour(100000);
    }

}

上面的是效率最高的一種方式。

以下的CODE,是我對4種方式的效率比較:

package com.company;

/**
 * 求100以內素數(質數) 最終方案:不需要迴圈每一次判斷,
 * 1.所有偶數都不是質數
 * 2.所有奇數除以偶數都除不斷,只需要判斷對奇數取餘,減少判斷次數
 * 3.大於該數字二次根的數字 是不能整除的。減少迴圈數字範圍。
 */
public class PrimeNumber {
    //第一種方法
    private boolean isPrimeNumberOne(int number) {
        for (int j = 2; j < number; j++) {
            if (number % j == 0) return false;
        }
        return true;
    }

    private void methodOne(int number) {
        long start = System.currentTimeMillis();
        for (int i = 2; i < number; i++) {
            if (isPrimeNumberOne(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodOne 花費時間:"+(end-start)+"ms");
    }

    //第二種方法
    private boolean isPrimeNumberTwo(int number) {
        for (int j = 2; j < number/2; j++) {
            if (number % j == 0) return false;
        }
        return true;
    }

    private void methodTwo(int number) {
        long start = System.currentTimeMillis();
        for (int i = 2; i < number; i++) {
            if (isPrimeNumberTwo(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodTwo 花費時間:"+(end-start)+"ms");
    }

    //第三種方法
    private boolean isPrimeNumberThree(int number) {
        double sqrt = Math.sqrt(number); //必須把 Math.sqrt(number) 提前賦值好,要不然放在 sqrt 處,每次比較都會計算一次,影響效能。
        for (int j = 2; j < sqrt; j++) {
            if (number % j == 0) return false;
        }
        return true;
    }

    private void methodThree(int number) {
        long start = System.currentTimeMillis();
        for (int i = 2; i < number; i++) {
            if (isPrimeNumberThree(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodThree 花費時間:"+(end-start)+"ms");
    }

    //第四種方法
    private boolean isPrimeNumberFour(int number) {
        double sqrt = Math.sqrt(number); //必須把 Math.sqrt(number) 提前賦值好,要不然放在 sqrt 處,每次比較都會計算一次,影響效能。
        for (int j = 3; j < sqrt; j+=2) {
            if (number % j == 0) return false;
        }
        return true;
    }

    private void methodFour(int number) {
        long start = System.currentTimeMillis();
        if (number>=2) System.out.println("Number:2 Is Prime Number");
        for (int i = 3; i < number; i+=2) {
            if (isPrimeNumberFour(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodFour 花費時間:"+(end-start)+"ms");
    }


    public static void main(String[] args) {
        PrimeNumber primeNumber = new PrimeNumber();
        long start = System.currentTimeMillis();
        primeNumber.methodOne(500000);
        long end = System.currentTimeMillis();
        long methodOne = end - start;
        start = System.currentTimeMillis();
        primeNumber.methodTwo(500000);
        end = System.currentTimeMillis();
        long methodTwo = end - start;
        start = System.currentTimeMillis();
        primeNumber.methodThree(500000);
        end = System.currentTimeMillis();
        long methodThree = end - start;
        start = System.currentTimeMillis();
        primeNumber.methodFour(500000);
        end = System.currentTimeMillis();
        long methodFour = end - start;
        System.out.println("one:"+methodOne+"two:"+methodTwo+"three:"+methodThree+"four:"+methodFour);
    }

}

四種方式,以50W的資料測試:(單位是ms)

one:30321two:13883three:343four:289

我們可以看到,30s,13s,0.34s,0.28s。這個差距還是挺大的。

當資料量更大的時候,這些差距會更加明顯