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

 

 

posted @ 2013-05-15 11:12  老鱼_678  阅读(1790)  评论(5编辑  收藏  举报