求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。這個差距還是挺大的。
當數據量更大的時候,這些差距會更加明顯