質數的定義 算法
一個數,若是隻有1和它自己兩個因數,這樣的數叫作質數,又稱素數。 編程
試除判斷法 函數
算法描述:從上述定義可知,素數不能被1和它自己以外的數整除,因此,判斷一個數x是否素數只要看它是否能被2~sqrt(x)間的數整除便可;而求N內全部素數則是循環重複上述過程。 學習
C語言實現: 優化
#include <time.h> #include <malloc.h> #define N 100000 // 簡單試除判斷法 Ver1 int SimpleDivisionV1(int n) { int i,j; // 素數數量統計 int count = 0; // 分配存放結果的空間 int* primes = (int*)malloc( sizeof(int)*n ); // 2是素數誰都知道,不算了 primes[count++] = 2; // 循環計算3~n間的數 for (i=3; i<=n; i++) { // 爲何是sqrt(i),思考一下 for (j=2; j<=sqrt(i); j++) { // i被j整除,顯然不是素數了 if (i%j == 0) break; } // i不能被2~sqrt(i)間的數整除,素數也 if (j > sqrt(i)) { primes[count++] = i; } } // 因輸出費時,且和算法核心相關不大,故略 // 釋放內存,別忘了傳說中的內存泄漏 free(primes); return count; } void main() { int count; clock_t start, end; // time函數不夠精確,用clock湊合一下吧 start = clock(); count = SimpleDivisionV1(N); end = clock(); printf("[%d]之內素數個數:%d, 計算用時:%d毫秒\n", N, count, end-start); getch(); }
計算結果:
[100000]之內素數個數:9592, 計算用時:468毫秒
[1000000]之內素數個數:78498, 計算用時:10859毫秒
[5000000]之內素數個數:348513, 計算用時:103560毫秒 code
噢噢,算算十萬還行,百萬就10秒多了,並且時間增加很快,這不行,得優化一下! 內存
優化分析: get
仔細研究一下SimpleDivisionV1咱們能夠發現如下幾個問題: io
根據上面兩點,咱們可將SimpleDivisionV1升級爲SimpleDivisionV2,以下 效率
// 簡單試除判斷法 Ver2 int SimpleDivisionV2(int n) { int i, j, k, stop; // 素數數量統計 int count = 0; // 分配存放結果的空間 int* primes = (int*)malloc( sizeof(int)*n ); // 2是素數誰都知道,不算了 primes[count++] = 2; stop = count; // 循環計算3~n間的數 for (i=3; i<=n; i++) { k = sqrt(i); // 在循環條件中重複調用sqrt是低效作法,故引入k while (primes[stop] <= k && stop < count) stop++; // stop幹什麼用,思考一下 for (j=0; j<stop; j++) { if (i%primes[j] == 0) break; } // i不能被2~sqrt(i)間的素數整除,天然也不能被其餘數整除,素數也 if (j == stop) { primes[count++] = i; } } // 因輸出費時,且和算法核心相關不大,故略 // 釋放內存,別忘了傳說中的內存泄漏 free(primes); return count; }
而後將main中調用的函數替換爲SimpleDivisionV2,在看一下執行結果:
[100000]之內素數個數:9592, 計算用時:46毫秒
[1000000]之內素數個數:78498, 計算用時:546毫秒
[5000000]之內素數個數:348513, 計算用時:3515毫秒
[10000000]之內素數個數:664579, 計算用時:8000毫秒
很開心的看到,通過優化,速度提升了幾十倍,尤爲是時間增加曲線的坡度變小了,N值越大,V2函數比V1的效率就越高
對於試除判斷這種質數算法來講,三藏認爲SimpleDivisionV2基本已經接近極限,不大可能有量級上的突破了,有興趣的朋友能夠本身進一步優化。初學者除了參看上述例子外,能夠嘗試作各類修改及細節優化,也能夠將除法變乘法,多加練習是學習編程的好方法。
雖然,上例中V2已經比V1快了不少了,但隨着N的增大,耗時仍是很多,那麼咱們還有更好的方法嗎?