zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    微信小程序&#183;前端-锦囊
    邓_ HTML+CSS总结
    npm
    js 中计算两个坐标点之间的距离
    微信小程序picker组件改变点击触发区域
    微信小程序获取手机号失败? | 邓士鹏
    uniapp 实现转发到朋友圈 新功能
    git 初始化项目
    uniapp 同步加载
    mkv转换mp4 无损转换
  • 原文地址:https://www.cnblogs.com/tmywu/p/3079403.html
Copyright © 2011-2022 走看看