Miller-Rabin 米勒拉宾素性检测

1、什么是Miller-Rabin

Miller - Rabin 算法是一种用于判断一个数是否为素数的概率性算法。在密码学等领域,经常需要快速判断一个大整数是否为素数。传统的试除法对于大整数效率极低,而 Miller - Rabin 算法能够在较短时间内以较高的概率判断一个数是否为素数。

2、相关数学基础

费马小定理

如果p是素数,a是整数且a与p互质(即 gcd(a,b)=1 ),那么eq?a%5E%7Bp-1%7D%5Cequiv%201%28modp%29。不过费马小定理的逆定理不成立,即满足eq?a%5E%7Bp-1%7D%5Cequiv%201%28modp%29的p不一定是素数。这就是为什么单纯依赖费马小定理来判断素数会有问题,Miller-Rabin算法就是在此处进行改进。

反例:卡迈克尔数(伪质数)

卡迈克尔数 
 

定义:对于合数n,如果对于所有与n互质的正整数b,都有同余式eq?b%5E%7Bn-1%7D%5Cequiv%201%28mod%20n%29成立,则称合数n为卡迈克尔数。
性质:

  • 至少是三个不同素数的乘积:每个卡迈克尔数至少是三个不同素数的乘积,例如最小的卡迈克尔数eq?561%3D3%5Ctimes%2011%5Ctimes%2017
  • 满足 Korselt 准则:卡迈克尔数的等效定义,当正合数n满足以下三个性质时,它就是一个卡迈克尔数:必须包含不止一个质因数;质因数均不重复;对于每一个能被n整除的质数p,eq?p-1 也可以被 eq?n-1 整除。


因为对于卡迈克尔数n,都有eq?b%5E%7Bn-1%7D%5Cequiv%201%28mod%20n%29成立,但n不是素数(费马小定理的逆定理不成立)

二次探测定理

如果p是奇素数,x是小于p的正整数,且eq?x%5E%7B2%7D%5Cequiv%201%28modp%29,那么eq?x%3D1或者eq?x%3Dp-1

3、算法步骤

如果先不考虑卡迈克尔数,常规判断n是否是素数(概率):枚举底数eq?a_%7Bx%7Deq?a_%7Bx%7D%20%3C%20n,判断eq?a_%7Bx%7D%5E%7Bn-1%7D%20%5Cmathbf%7Bmod%7D%20n等于多少,如果eq?a_%7Bx%7D%5E%7Bn-1%7D%20%5Cmathbf%7Bmod%7D%20n%20%3D%201,那么n大概率是素数。

但卡迈克尔数不是素数,却满足eq?a_%7Bx%7D%5E%7Bn-1%7D%20%5Cmathbf%7Bmod%7D%20n%20%3D%201,所以需要筛掉卡迈克尔数,使用Miller-Rabin算法能进行有效筛掉卡迈克尔数。

如何筛掉卡迈克尔数呢?
第一次是进行费马小定理,第二次通过二次探测原理来筛掉卡迈克尔数。

二次探测定理:
假设 p 是一个素数,那么 p 显然是奇数,所以 p-1 显然是偶数。
假设有eq?a%5E%7Bp-1%7D,p-1 是偶数,令eq?%5Cfrac%7Bp-1%7D%7B2%7D%3Dm,则有eq?a%5E%7Bp-1%7D%20%3D%20a%5E%7B%5Cfrac%7Bp-1%7D%7B2%7D%5Ctimes%202%7D%20%3D%20a%5E%7Bm%5Ctimes%202%7D%20%3D%20%28a%5E%7Bm%7D%29%5E%7B2%7D
由费马小定理得,eq?%28a%5E%7Bm%7D%29%5E%7B2%7D%5Cmathbf%7Bmod%7D%20p%3D1
那么eq?%28%28a%5E%7Bm%7D%29%5E%7B2%7D-1%29%5Cmathbf%7Bmod%7D%20p%3D0,平方差变形可得eq?%28a%5E%7Bm%7D+1%29%28a%5E%7Bm%7D-1%29%5Cmathbf%7Bmod%7Dp%3D0,则说明eq?a%5E%7Bm%7D%5Cmathbf%7Bmod%7Dp%20%3D%201eq?a%5E%7Bm%7D%5Cmathbf%7Bmod%7Dp%20%3D%20p-1

也就是说,第一次是进行了费马小定理eq?%28a%5E%7Bm%7D%29%5E%7B2%7D%5Cmathbf%7Bmod%7D%20p%3D1,但此时还没筛去卡迈克尔数,就需要通过判断eq?a%5E%7Bm%7D%5Cmathbf%7Bmod%7Dp%20%3D%201eq?a%5E%7Bm%7D%5Cmathbf%7Bmod%7Dp%20%3D%20p-1是否成立,如果成立则说明不是卡迈克尔数且大概率是素数,否则不是素数。

如果将 p-1=t\times 2^{m},可得a^{p-1} = a^{t\times 2^{m}},令a^{t\times 2^{i}},0\leq i\leq m,可得序列a^{t},(a^{t})^{2},(a^{t})^{3},...,a^{p-1},通过同余定理,可得序列每一项mod p后的序列为,由同余定理得知,mod p后的序列里,如果是x ->...-> -1 -> 1...序列中间有一个-1的,那么-1之后就只能是1;如果中间没有-1,那么之后也就不会是1;所以有:

  1. p是质数:要么起始就是1,要么中间出现-1
  2. p是合数:中间没有出现-1

9c8329fc5e164e04b17543bc5d446e5a.png

4、代码实现

python

import random
def miller_rabin(n, k):
    if n == 2:
        return True
    if n % 2 == 0:
        return False
    # 分解n - 1为2^s * d的形式
    s = 0
    d = n - 1
    while d % 2 == 0:
        s += 1
        d //= 2
    for _ in range(k):
        a = random.randint(2, n - 2)
        x = pow(a, d, n)
        if x == 1 or x == n - 1:
            continue
        for _ in range(s - 1):
            x = pow(x, 2, n)
            if x == n - 1:
                break
        else:
            return False
    return True

cpp

#include <iostream>
#include <cstdlib>
#include <ctime>

// 快速幂取模运算,用于计算 (a^b) % m
int pow_mod(int a, int b, int m) {
    int result = 1;
    a %= m;
    while (b > 0) {
        if (b & 1) {
            result = (result * a) % m;
        }
        a = (a * a) % m;
        b >>= 1;
    }
    return result;
}

// Miller-Rabin素性测试算法
bool miller_rabin(int n, int k) {
    if (n == 2) return true;
    if (n % 2 == 0 || n < 2) return false;

    // 分解 n - 1 为 2^s * d 的形式
    int s = 0;
    int d = n - 1;
    while (d % 2 == 0) {
        s++;
        d /= 2;
    }

    // 进行k轮测试
    for (int i = 0; i < k; i++) {
        int a = rand() % (n - 3) + 2;  // 选取 [2, n - 2] 之间的随机数作为底数
        int x = pow_mod(a, d, n);
        if (x == 1 || x == n - 1) continue;

        bool composite = true;
        for (int r = 1; r < s; r++) {
            x = pow_mod(x, 2, n);
            if (x == n - 1) {
                composite = false;
                break;
            }
        }
        if (composite) return false;
    }
    return true;
}

//测试
int main() {
    srand(static_cast<unsigned int>(time(nullptr)));
    int num = 121;  // 这里可以替换成你想要测试的数
    int round = 5;  // 测试轮数,可以根据需求调整
    if (miller_rabin(num, round)) {
        std::cout << num << " 可能是素数" << std::endl;
    } else {
        std::cout << num << " 是合数" << std::endl;
    }
    return 0;
}

5、时间复杂度

dff009a188844fce8197261fc5d13904.png

### 回答1: Miller-Rabin素性测试算法是一种用于判断一个数是否为质数的算法。该算法基于费马小定理,使用随机数进行迭代运算,可以高效地判断一个数是否为质数。 具体来说,该算法将要判断的数记作n,随机选取一个小于n的正整数a,将a与n进行求模运算得到b。如果b等于0或者b等于n-1,则继续选择下一个a。否则,将b平方并对n取模,得到c。如果c等于1或者c等于n-1,则继续选择下一个a。否则,不断平方c并对n取模,直到c等于1或者迭代次数达到了一定阈值。如果c等于1,则n可能是一个合数;如果迭代过程中出现了c等于n-1的情况,则n很可能是一个质数。 为了提高判断的准确性,Miller-Rabin算法会进行多次随机迭代,每次选取不同的随机数a。随机迭代次数越多,判断结果的准确性越高,但计算时间也越长。 总之,Miller-Rabin素性测试算法是一种高效、准确的判断一个数是否为质数的算法,被广泛应用于密码学、计算机科学等领域。 ### 回答2: Miller-Rabin素性测试算法是一种用于判断一个数是否为素数的快速算法。该算法基于费马小定理,利用随机数的特性来判断一个数是否为素数。该算法的优势在于速度快且准确率高,同时能够应对大整数的素性测试。 该算法的具体步骤如下: 1. 首先确定待测试的数n,如果n为偶数,则直接判断n是否等于2,如果是则n为素数,因为2是最小的质数。 2. 若n为奇数,则写成n-1=2^r * d的形式,其中r为非负整数,d为奇数。 3. 接着随机选取一个整数a,且1 < a < n-1。计算a^d mod n,如果结果等于1或n-1,则可以认为n有很大的可能是素数,结束测试。 4. 若结果不等于1或n-1,则重复计算a^(2^j*d) mod n,直到出现下面两种情况之一:结果为1,或者出现了j=0,1,...,r-1时,结果为n-1。 5. 如果满足上述两种情况之一,则认为n有很大的可能是素数,结束测试。否则,重新随机选取一个a,重复上述操作进行测试。 需要说明的是,该算法的准确率可以通过多次测试进行提高。一般来说,重复进行10~20次检验,即可认为检验结果是正确的。 总之,Miller-Rabin素性测试算法是一种简单高效的素数测试算法,可以广泛应用于需要高精度计算的场合。它在加密、密码学等领域中,有着重要的应用价值。 ### 回答3: Miller-Rabin素性测试算法是一种用于判断一个数是否为素数的算法,名字来源于两位发明者:Gary L. Miller和Michael O. Rabin。与其它素数检测算法不同,Miller-Rabin素性测试算法有极高的概率能够正确地识别素数,其准确率可以达到误判的可能性小于$\frac{1}{4}$。 Miller-Rabin素性测试算法的基本原理是利用了费马小定理和欧拉判别法,即对于一个素数$p$和$a<p$,有$a^{p-1} \equiv 1 \pmod{p}$,而对于合数$n=pq$,其中$p,q$为大于1的素数,则在模n下,$a^{n-1} \equiv 1 \pmod{n}$,并且除了一些“小概率事件”外,$a^{(n-1)/2} \equiv \pm 1 \pmod{n}$。 Miller-Rabin 素性测试算法的流程如下: 1.将$n-1$分解成$2^sd$的形式,其中$d$是奇数。 2.对于给定的$a<n$,利用费马小定理,计算$a^d \pmod{n}$。 3.如果$a^d \equiv 1 \pmod{n}$,则认为$n$可能是一个素数,算法结束。 4.对于$0\leq r \leq s-1$,如果$a^{2^rd} \equiv -1 \pmod{n}$,则认为$n$可能是一个素数,算法结束。 5.如果$a^{2^sd} \not \equiv 1 \pmod{n}$或$a^{2^{r}d} \not \equiv -1 \pmod{n}$(其中$0\leq r \leq s-1$),则认为$n$不是素数,算法结束。 通过多次进行以上的步骤,可以提高算法的准确率。 Miller-Rabin素性测试算法是一种在计算机领域经常使用的算法,其特点是计算量较小、正确率较高、可扩展性好。在计算机安全领域,该算法被广泛地应用于RSA算法中,用于加密和解密数据。虽然该算法在某些情况下会出现一定的偏差,但是通过多次计算,可以达到一个非常高的准确率。因此,在实际应用中,Miller-Rabin素性测试算法是一个非常实用的工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

みずいろ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值