[原]素數斷定

大學生程序代寫
路漫漫其修遠兮,吾將上下而求索!

素數斷定算法

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/

做者:chao1983210400 發表於2013-7-25 19:33:55 原文連接
閱讀:10 評論:0 查看評論
相關文章
相關標籤/搜索