素数测试算法

来源:互联网 发布:软件中间件 编辑:程序博客网 时间:2024/05/22 13:43

昨天刷LeetCode 时候遇到判断素数的问题 204.Count Primes ,想起hihocoder上之前也出现过,但是当时没看。

于是今天整理了一些关于判断一个数是否是素数的知识。因为大部分的内容都是别人的,所以下文主要是提供一些参考链接

以下假设要判断的数为n

1、传统判断方式

判断n是否能被2-n^(1/2)中的数整除,即 204. Count Primes 的解法1


2、 埃拉托斯特尼筛法(Sieve of Eratosthenes),即 204. Count Primes 的解法2


3、Miller Rabin 素数测试算法

Miller Rabin 素数测试算法属于数论中的知识,需要耐心的阅读。以下提供几个参考链接

a.维基百科 Miller–Rabin primality test 

b.中文的解释和算法的由来 Matrix67: The Aha Moments

c.Miller Rabin 算法的具体实现(包含多种语言)Miller–Rabin primality test

d.hihocoder的题,(但是当时没报名似乎没权限提交)数论一·Miller-Rabin质数测试

根据参考链接给的伪代码,我用C#实现了一下,但是没有测试(可能有误)。不过该算法在LeetCode上测试似乎会超时?

伪代码:

Input: n > 2, an odd integer to be tested for primality;       k, a parameter that determines the accuracy of the testOutput: composite if n is composite, otherwise probably primewrite n − 1 as 2s·d with d odd by factoring powers of 2 from n − 1LOOP: repeat k times:   pick a randomly in the range [2, n − 1]   x ← ad mod n   if x = 1 or x = n − 1 then do next LOOP   for r = 1 .. s − 1      x ← x2 mod n      if x = 1 then return composite      if x = n − 1 then do next LOOP   return compositereturn probably prime

C#:

private bool isPrime(int n, int k)        {            if (n < 2)                return false;            if (n == 2)                return true;            if (n % 2 == 0)                return false;            int num = n - 1, s = 0, tmp, mod;            while (num % 2 == 0)            {                s++;                num >>= 1;            }            Random rand = new Random();            for (int i = 0; i < k; i++)            {                int a = rand.Next(n - 2) + 2;                a = 2;                int d = num;                //mod = (int)Math.Pow(a,d) % n;                tmp = 0;                mod = 1;                while (tmp < d)                {                    mod = (int)(mod * a) % n;                    tmp++;                }                if (mod == 1 || mod == n - 1)                    continue;                int j;                bool flag = false;                for (j = 1; j < s; j++)                {                    mod = (mod * mod) % n;                    if (mod == 1)                        return false;                    if (mod == n - 1)                    {                        flag = true;                        break;                    }                }                if (!flag)                    return false;            }            return true;        }




0 0