合數過濾篩選法
演算法描述:我們知道,素數
n不能被
2~(n-1)
間的任何數整除;反過來看,只要能被
2~(n-1)
間的任何數整除的
n,都不是素數。所以我們可以採用乙個簡單的排除法:就是對
n以內的所有數,只要逐個去除值為
2~(n-1)
的倍數的數,剩下的就是素數。
c
語言實現
// 合數過濾篩選法 ver1
// 引數:n 求解n以內(包括n)的素數
// 返回值:n以內素數個數
int compositenumfilterv1(int n)
// 寫程式要注意排版和留空,方便閱讀,也可減少出錯機率
// 以2~(n-1)為因子過濾合數
for (i=2; i < n; i++) }
// 統計素數個數
for (i=2; i<=n; i++)
// 因輸出費時,且和演算法核心相關不大,故略
// 釋放記憶體,別忘了傳說中的記憶體洩漏
free(flag);
return count;
}
在上文給出的
main
函式中以不同引數呼叫
compositenumfilterv1
函式,得到執行結果如下:
[100000]
以內素數個數:
9592,
計算用時:
15毫秒
[1000000]
以內素數個數:
78498,
計算用時:
125毫秒
[5000000]
以內素數個數:
348513,
計算用時:
2578
毫秒[10000000]
以內素數個數:
664579,
計算用時:
6281毫秒
注:因程式是非獨占性執行的,所以時間不是完全精確的,但基本能反映實情
顯然,比上文中的試除法要快,而且誰都可以看到上例是乙個未經優化的粗陋版本,好多地方是三藏故意採用比較低效做法,為了與後文的優化版比較,凸顯優化之重要,也為了初學者記住別採用類似低效做法,下面我們開始優化之旅
優化分析
上面compositenumfilterv1
函式存在的問題有: 1.
在外層迴圈,需要一直執行到
n-1嗎?不要,因為
n/2~n-1
間的數顯然不能整除n
2.在內層迴圈中重複使用
i*j顯然是低效的,考慮到計算機中加減運算速度比乘除快可以考慮變乘法為加法 3.
在迴圈修改
flag
過程中,其實有很多數會被重複計算若干次,比如
6=2*3=3*2
,會被重複置
0,類似操作很多,所以我們得設法避免或減少
flag
重複置0
據上述分析,我們可將程式優化如下:
// 合數過濾篩選法 ver2
// 引數:n 求解n以內(包括n)的素數
// 返回值:n以內素數個數
int compositenumfilterv2(int n)
flag[2] = 1;
flag[3] = 1;
flag[5] = 1;
flag[7] = 1;
flag[11] = 1;
flag[13] = 1;
// 從17開始filter,因為2,3,5,7,11,13的倍數早被kill了
// 到n/13止的,哈哈,少了好多吧
int stop = n/13;
for (i=17; i <= stop; i++)
}// 統計素數個數
for (i=2; i<=n; i++)
// 因輸出費時,且和演算法核心相關不大,故略
// 釋放記憶體,別忘了傳說中的記憶體洩漏
free(flag);
return count;
}
再看compositenumfilterv3
執行結果:
[1000000]
以內素數個數:
78498,
計算用時:
15毫秒
[5000000]
以內素數個數:
348513,
計算用時:
203毫秒
[10000000]
以內素數個數:
664579,
計算用時:
515毫秒
[100000000]
以內素數個數:
5761455,
計算用時:
6421毫秒
再次優化後速度提公升了又一倍左右
素數篩法(素數篩 線性篩)
求素數的方法在現階段可以總結為三種 這種方法最為簡單但效率太低,經過優化時間複雜度最低是o n sqrt n 輸入乙個n,輸出n以內所有素數 include intprime int n if flag 0 優化 printf d i intmain 素數篩法原理 2是素數,那麼2的所有倍數都是合數...
素數判定,素數篩
這些零碎的知識點每個都學過n次了,但隔一段時間就會忘,記錄下來 素數定義 只能被自身和1整除的大於1的正整數 通過這個定義,我們就可以得出判斷素數的 這裡用到了cmath中的sqrt函式,其原型為double sqrt double 所以在取上界的時候,為了避免double帶來的精度丟失,寧可多列舉...
素數與素數篩
素數篩法 線性篩法 啊,耳熟能詳。素數又稱質數,乙個大於1 11的自然數,除了1 11和它本身外,不能被其他自然數整除,換句話說就是該數除了1 11和它本身以外不再有其他的因數 否則稱為合數。啊!1 11不是素數啊 啊,也耳熟能詳了,暴力列舉一下除1 11和本身的自然數是否會被整除。bool is ...