C# 判斷給定大數是否為質數,目標以快速度得到正確的計算結果。


標題是一個測試題。在看到這道題的時候,第一反應這是一道考程序復雜度的題,其次再是算法問題。

我們先來看看質數的規則:

Link:http://en.wikipedia.org/wiki/Prime_number

C#求質數代碼:

1         public bool primeNumber(int n){
2             int sqr = Convert.ToInt32(Math.Sqrt(n));
3             for (int i = sqr; i > 2; i--){
4                 if (n % i == 0){
5                     b = false;
6                 }
7             }
8             return b;
9         }


顯然以上代碼的程序復雜度為N

我們來優化下代碼,再來看下面代碼:

 1         public bool primeNumber(int n)
 2         {
 3             bool b = true;
 4             if (n == 2)
 5                 b = true;
 6             else
 7             {
 8                 int sqr = Convert.ToInt32(Math.Sqrt(n));
 9                 for (int i = sqr; i > 2; i--)
10                 {
11                     if (n % i == 0)
12                     {
13                         b = false;
14                     }
15                 }
16             }
17             return b;
18         }

通過增加初步判斷使程序復雜度降為N/2。

以上兩段代碼判斷大數是否質數的正確率是100%,但是對於題干

  1.滿足大數判斷;

  2.要求以最快速度得到正確結果;

顯然是不滿足的。上網查了下最快算法得到准確結果,公認的一個解決方案是Miller-Rabin算法

Link:http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test

Miller-Rabin 基本原理是通過隨機數算法判斷的方式提高速度(即概率擊中),但是犧牲的是准確率。

Miller-Rabin 對輸入大數的質數判斷的結果並不一定是完全准確的,但是對於本題來說算是一個基本的解題辦法了。

Miller-Rabin C# 代碼:

 1 public bool IsProbablePrime(BigInteger source) {
 2             int certainty = 2;
 3             if (source == 2 || source == 3)
 4                 return true;
 5             if (source < 2 || source % 2 == 0)
 6                 return false;
 7 
 8             BigInteger d = source - 1;
 9             int s = 0;
10 
11             while (d % 2 == 0) {
12                 d /= 2;
13                 s += 1;
14             }
15 
16             RandomNumberGenerator rng = RandomNumberGenerator.Create();
17             byte[] bytes = new byte[source.ToByteArray().LongLength];
18             BigInteger a;
19 
20             for (int i = 0; i < certainty; i++) {
21                 do {
22                     rng.GetBytes(bytes);
23                     a = new BigInteger(bytes);
24                 }
25                 while (a < 2 || a >= source - 2);
26 
27                 BigInteger x = BigInteger.ModPow(a, d, source);
28                 if (x == 1 || x == source - 1)
29                     continue;
30 
31                 for (int r = 1; r < s; r++) {
32                     x = BigInteger.ModPow(x, 2, source);
33                     if (x == 1)
34                         return false;
35                     if (x == source - 1)
36                         break;
37                 }
38 
39                 if (x != source - 1)
40                     return false;
41             }
42 
43             return true;
44         }


以上是我對本題的解題答案,歡迎大家討論和提供更優辦法。

代碼戳:files.cnblogs.com/tmywu/PrimeNumberProject.zip

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM