素數斷定算法
1. 素數斷定問題html
素數斷定問題是一個很是常見的問題,本文介紹了經常使用的幾種斷定方法。算法
2. 原始算法數據結構
素數的定義是,除了能被1和它自己整除而不能被其餘任何數整除的數。根據素數定義 只須要用2到n-1去除n,若是都除不盡,則n是素數,不然,只要其中有一個數能整除則n不是素數。app
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
bool
is_primer1(
int
num) {
int
i;
for
(i = 2; i < num; i++) {
if
(num % i == 0) {
return
true
;
}
}
return
false
;
}
|
3. 改進算法post
n不是素數,則n可表示爲a*b,其中2<=a<=b<=n-1,則a,b中必有一個數知足:1<x<=sqrt(n),於是,只須要用2~sqrt(n)去除n,這樣就獲得一個複雜度爲O(sqrt(n))的算法優化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
bool
is_primer2(
int
num) {
int
i;
int
upper =
sqrt
(num);
printf
(
"primer2:%d\n"
, upper);
for
(i = 2; i <= upper; i++) {
if
(num % i == 0) {
return
true
;
}
}
return
false
;
}
|
4. 篩選算法url
更高效地素數判斷方法應該是將素數預先保存到一個素數表中,當判斷一個數是否爲素數時,直接查表便可。這種方法須要解決兩個問題:spa
(1) 怎樣快速獲得素數表?(採用篩選方法).net
(2) 怎樣減小素數表的大小?(採用位圖數據結構)code
對於1到n所有整數,逐個判斷它們是不是素數,找出一個非素數,就把它挖掉,最後剩下的就是素數。具體方法是:
<1> 定義is_primer[i] = true;
<2> 從2開始,依次遍歷整個is_primer(直到sqrt(N)),若是is_primer[i]=true,則is_primer[n*i]=false
如1,2,3,4,5,6,7,8,9,10,則
從2開始遍歷:
is_primer[2]=true,則is_primer[4]= is_primer[6]= is_primer[8]= is_primer[10]= true
is_primer[3]=true,則is_primer[6]= is_primer[9]= true
爲了減小內存使用率,算法使用了位圖數據結構,關於位圖,可參考:http://dongxicheng.org/structure/bitmap/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
bool
load_primer_table1() {
//保存素數表
int
i;
for
(i = 1; i < INT_MAX; i++) {
if
(i % 2 != 0
//偶數必定不是素數
&& is_primer2(i)) {
set(i);
}
}
}
bool
load_primer_table2() {
//另外一種更快的方法保存素數表
int
i, j;
for
(i = 1; i <= INT_MAX; i++) {
if
( i % 2) {
set(i);
}
else
{
clear(i);
}
}
int
upper =
sqrt
(INT_MAX);
for
(i = 1; i <= upper; i++) {
if
(test(i)) {
for
(j = i + i; j < INT_MAX; j += i)
set(i);
}
}
}
bool
is_primer3(
long
num) {
//查表判斷是否爲素數
if
(test(num))
return
true
;
return
false
;
}
|
5. 優化的篩選算法
(1) 存儲方式優化
仍然採用位圖方式存儲,只不過是位圖中只存儲奇數,這樣一會兒節省了一半空間(須要的空間僅爲4G/(32*2)=64MB)
存儲空間優化後,算法效率也會提高不少,如:1,2,…,30
只需存儲3,5,7,9,11,13,15,17,19,21,23,25,27,29
i=0, is_primer[0] =true, 把下標[3][6][9][12],即9,15,21,27,標爲false
i=1, s_primer[0] =true,把下標爲[6][11],即15,25標爲false
i=2, 2*i+3>sqrt(30),結束
即:i=s, 把下標爲s(2*t+1)+3t,其中,t=1,2,3,…中全部的的is_primer置爲false
(2) 優化刪選算法
a是素數,則下一個起點是a*a,把後面的全部的a*a+2*i*a篩掉。即欲求n之內的素數,就先把sqrt(n)內的素數求出來,用已經求得的素數來篩出後面的合數。
6. 總結
至今爲止,沒有任何人發現素數的分佈規律,也沒有人能用一個公式計算出全部的素數。關於素數的不少的有趣的性質或者科學家的努力,如:
(1) 高斯猜想,n之內的素數個數大約與n/ln(n)至關,或者說,當n很大時,二者數量級相同。這就是著名的素數定理。
(2) 十七世紀費馬猜想,2的2^n次方+1,n=0,1,2…時是素數,這樣的數叫費馬素數,惋惜當n=5時,2^32+1就不是素數,至今也沒有找到第六個費馬素數。
(3) 18世紀發現的最大素數是2^31-1,19世紀發現的最大素數是2^127-1,20世紀末人類已知的最大素數是2^859433-1,用十進制表示,這是一個258715位的數字。
(4) 孿生素數猜測:差爲2的素數有無窮多對。目前知道的最大的孿生素數是1159142985×2^2304-1和1159142985×2^2304+1。
(5) 歌德巴赫猜測:大於2的全部偶數均是兩個素數的和,大於5的全部奇數均是三個素數之和。其中第二個猜測是第一個的天然推論,所以歌德巴赫猜測又被稱爲1+1問題。我國數學家陳景潤證實了1+2,即全部大於2的偶數都是一個素數和只有兩個素數因數的合數的和。國際上稱爲陳氏定理。(摘自《http://chuanbindeng.blog.163.com/blog/static/67886226200982892139468/》)
7. 參考資料
http://www.doc88.com/p-5780302974.html
http://chuanbindeng.blog.163.com/blog/static/67886226200982892139468/