演算法-----求n以內素數(質數)
阿新 • • 發佈:2019-02-16
求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。這個差距還是挺大的。
當資料量更大的時候,這些差距會更加明顯