1. 程式人生 > >Java求n以內的所有質數

Java求n以內的所有質數

質數(prime number)又稱素數,有無限個。一個大於1的自然數,除了1和它本身外,不能被其他自然數整除,換句話說就是該數除了1和它本身以外不再有其他的因數;否則稱為合數。

方法1:根據質數的定義求解;

方法2:對方法1作進一步優化,僅需判斷到該數的平方根;

方法3:基於規律除了2,所有的質數都是奇數;如果一個數不能被它之前的質數整除,那麼這個數是質數”進一步優化程式。

示例程式如下:

package test;

import java.util.ArrayList;
import java.util.List;

public class FindPrime {

	public static void main(String[] args) {
		long time = System.nanoTime();
		System.out.println(findPrime1(10000).size());
		System.out.println(System.nanoTime() - time);
		
		time = System.nanoTime();
		System.out.println(findPrime2(10000).size());
		System.out.println(System.nanoTime() - time);
		
		time = System.nanoTime();
		System.out.println(findPrime3(10000).size());
		System.out.println(System.nanoTime() - time);
	}

	public static List<Integer> findPrime1(int n) {
		List<Integer> primes = new ArrayList<Integer>();
		primes.add(2);
		for(int i = 3; i <= n; i++) {
			for(int j = 2; j < i; j++) {
				if(i % j == 0)	break;
				if(j == i-1)	primes.add(i);
			}
		}
		return primes;
	}

	public static List<Integer> findPrime2(int n) {
		List<Integer> primes = new ArrayList<Integer>();
		primes.add(2);
		for(int i = 3; i <= n; i++) {
			int tmp = (int)Math.sqrt(i) + 1;
			for(int j = 2; j <= tmp; j++) {
				if(i % j == 0)	break;
				if(j == tmp)	primes.add(i);
			}
		}
		return primes;
	}

	public static List<Integer> findPrime3(int n) {
		List<Integer> primes = new ArrayList<Integer>();
		primes.add(2);
		for(int i = 3; i <= n; i+=2) {
			for(int j = 0; j < primes.size(); j++) {
				if(i % primes.get(j) == 0)	break;
				if(j == primes.size() - 1) { primes.add(i); break; }
			}
		}
		return primes;
	}

}
執行結果截圖:


結果分析:

大家針對這個結果或許感到有點奇怪,為什麼方法三會比方法二慢?雖然方法三理論上快點,但是方法三需要遍歷list,而方法二不需要。除非當這個n特別大(我測到10^9,還是方法二優)時,不然方法二都是優於方法三的。所以我們認為最好的方法是:方法二 + 優化“除了2,所有的質數都是奇數”。