Miller-Rabin算法素检测介绍及实现(含c++和python实现代码)

目录

一、Miller-Rabin算法介绍

二、快速乘与快速幂

(一)、分析

(二)、快速乘代码

(三)、快速幂代码

三、完整Miller-Rabin代码

(一)、C++代码

(二)、python代码


一、Miller-Rabin算法介绍

        Miller-Rabin 算法(强伪素数检测)利用原理:若 n 为素数,则根据费马小定理:若n是一个素数,且(a,n)=1,则

a^{n-1}=1modn

且1𝑚𝑜𝑑𝑛只有 1 和-1 两个平方根。

        首先,假设n为一个非2素数,则 n-1 为一个偶数,任何一个偶数可以写成2^km的形式,其中m为一个奇数。随机选取a,满足1 ≤ 𝑎 ≤ 𝑛 − 1。将a^m(modm)赋值给一个新的变量b。如果,𝑏 ≡ 1(𝑚𝑜𝑑𝑛),则表明假设成立,n 为大于 2 的素数。否则,进行k次循环,每次循环判断,若𝑏≡−1(𝑚𝑜𝑑𝑛),则n为大于2的素数,否则将b^2(modm)赋值给b,继续循环。若最终没有得到𝑏≡−1(𝑚𝑜𝑑𝑛),则n为一个合数。

        且当n为2时,n-1=1,k=0,m=1,a=1,则b=1满足𝑏≡1(𝑚𝑜𝑑𝑛),说明Miller-Rabin算法对n为2同样适用。

            但该算法有概率出错

         1、在取 a 时,若 a 取到 1,则无论 n 是否为素数,a^m(modm)一定等于 1,即𝑏 ≡ 1(𝑚𝑜𝑑𝑛)

必定成立,导致将其判断为素数。因 a 若无法取到 1,只会影响到 2 是否为素数的判定,所以,在算法实现时可令 a 无法取到 1,且在生成 a 前判断是否为2。以使算法成功判断素数。                             

         2、当 a 取得 n-1 时,则因 m 必定为奇数,所以,

a^m+1=(n-1)^m+1=n((n-1)^{m-1}-(n-1)^{m-2}\cdots\dots+1)

此时𝑏 ≡ −1(𝑚𝑜𝑑𝑛)成立,会将合数误判为素数。

         3、因费马小定理的逆命题不成立,存在的合数。如:341=11\times31,若取a=2,2^{340}\equiv1mod341

         Miller-Rabin算法出现错误的概率约为\frac{1}{4},根据上述分析认为错误原因主要在于a的随机选取上,综上,可以通过多次随机选择a避免1,2情况的发生,以及降低发生3的概率,但多次取a会使判断时间变长,因(\frac{1}{4} )^6 ≈ 0.0002已经较小,所以在实现中可以取6次a分别判断。



二、快速乘与快速幂

(一)、分析

        在C++中,为测试较大的数据,采用long long类型,long long类型为8字节,即可计算64bit的数据,但在幂计算时会出现溢出现象,所以介绍一种快速乘与快速幂的运算方式,利用分治的思想进行幂运算,利用加法代替乘法,以防止溢出的发生。具体分析可参考大佬的文章

(二)、快速乘代码

long long mod_mul(long long a, long long b,long long n)
{
	long long result = 0;
	while (b > 0)
	{
		if (b & 1)
			result = (result + a) % n;
		a = (a + a) % n;
		b = b >> 1;
	}
	return result;
}

(三)、快速幂代码

long long mod_exp(long long a, long long b, long long n)
{
	long long result = 1;
	while (b > 0)
	{
		if (b & 1)
			result = mod_mul(result, a, n);
		a = mod_mul(a, a, n);
		b = b >> 1;
	}
	return result;
}

三、完整Miller-Rabin代码

(一)、C++代码

#include <iostream>
using namespace std;
long long mod_mul(long long a, long long b, long long n)//快速乘法
{
	long long result = 0;
	while (b > 0)
	{
		if (b & 1)//判断是否为偶数
			result = (result + a) % n;
		a = (a + a) % n;
		b = b >> 1;//除二操作
	}
	return result;
}
long long mod_exp(long long a, long long b, long long n)//快速幂
{
	long long result = 1;
	while (b > 0)
	{
		if ((b & 1) > 0)
			result = mod_mul(result, a, n);
		a = mod_mul(a, a, n);
		b = b >> 1;//除二操作
	}
	return result;
}
bool isprime(long long n)
{
	int k = 0;
	long long p = n - 1;
	while ((p & 1) == 0)//判断是否为奇数
	{
		p = p >> 1;//除二操作
		k++;
	}
	for (int i = 0; i < 6; i++)
	{
		long long a = rand() % (n - 1 - 1 + 1) + 1;
		long long b = mod_exp(a, p, n);
		bool flag = false;
		if (b == 1)
			continue;
		for (int j = 0; j < k; j++)
			if ((b + 1) % n == 0)
			{
				flag = true;
				break;
			}
			else
				b = (b * b) % n;
		if (flag)
			continue;
		return false;
	}
	return true;
}
int main()
{
	long long N;
	cin >> N;
	if (isprime(N))
		cout << N << " is prime!";
	else
		cout << N << " is composite!";
}

(二)、python代码

import random
def isprime(n):
    k,p=0,n-1
    while (p&1)==0:
        p=p>>1
        k+=1
    for j in range(6): 
        a=random.randint(1,n-1)
        b=pow(a,p,n)
        flag=0
        if b==1:
            continue
        for i in range(k):
            if (b+1)%n==0:
                flag=1
                break
            else:
                b=(b*b)%n
        if flag==1:
            continue
        else:
            return False
    return True
n=int(input())
if isprime(n):
    print(n,"is prime”)
else:
     print(n,"is composite")

  • 19
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Miller-Rabin算法Python实现如下: ``` def is_prime(n, k=10): if n == 2 or n == 3: return True if n <= 1 or n % 2 == 0: return False d = n - 1 s = 0 while d % 2 == 0: d //= 2 s += 1 for i in range(k): a = random.randint(2, n - 2) x = pow(a, d, n) if x == 1 or x == n - 1: continue for r in range(s - 1): x = pow(x, 2, n) if x == n - 1: break else: return False return True ``` 该代码使用了Python的内置函数`pow()`,并使用了随机数生成来提高判断数的正确性。 ### 回答2: Miller-Rabin算法是一种用于判断一个数是否为质数的算法,它的复杂度比较低,可以处理非常大的数。其原理是利用费马小定理,通过多次随机测试来判断一个数是否为合数。这种方法在理论上并不能保证完全正确,但是概率非常高,可以满足实际需求。 Python是一种非常流行的编程语言,对于实现Miller-Rabin算法非常方便。下面我们给出一个基本的Python实现代码如下: ``` import random def is_prime(n: int, k: int = 10) -> bool: if n in [2, 3]: return True if n == 1 or n % 2 == 0: return False r, s = 0, n - 1 while s % 2 == 0: r += 1 s //= 2 for _ in range(k): a = random.randint(2, n - 2) x = pow(a, s, n) if x == 1 or x == n - 1: continue for __ in range(r - 1): x = pow(x, 2, n) if x == n - 1: break else: return False return True ``` 代码中的参数`n`表示待判断的数,`k`表示进行随机测试的次数。在实际使用中,可以根据需要适当调整`k`的值以达到最佳效果。 首先对特殊情况进行判断,若`n`为2或3则返回True;若`n`为1或偶数则返回False。接着通过对`n`进行减一操作,将其变为偶数。然后通过循环将其分解为$r$和$s$两个因子,其中$s$是奇数。随后进行$k$次随机测试。每次测试,随机生成一个整数$a$,并将其幂次方取模。若$a^s\equiv1\pmod n$或$a^s\equiv n-1\pmod n$则说明此次测试没有发现`n`是合数的证据,可以直接进入下一轮测试。否则,将$a^s$不断平方取模$r$次,若其结果为$n-1$则说明此次测试没有发现`n`是合数的证据,可以进入下一轮测试。如果经过$k$次测试仍然没有发现`n`是合数的证据,则可以近似认为`n`是一个质数。 通过上述的Python代码实现,我们可以方便地判断一个数是否为质数,达到了实际应用的需要。在实际使用中,建议针对具体应用场景,对算法参数进行优化,以获得最佳效果。 ### 回答3: Miller-Rabin算法是一种用于判断一个数是否为质数的算法。该算法不需要求出该数的因子,只需要进行一定的判断即可。 Miller-Rabin算法需要随机选择测试因子,根据费马小定理进行测试。如果被测试数n是质数,那么对于任意的a(1<a<n),都有a^(n-1) ≡ 1 mod n。但如果n不是质数,那么大多数a^(n-1) ≢ 1 mod n。 Miller-Rabin算法的核心思想是对于单个测试因子的测试,最多只会出现两种情况:n是合数和n可能是质数。因此,我们使用k个随机测试因子进行测试,如果所有的测试都表明n是质数,那么n就很有可能是质数。一般情况下,k的取值为10-50。 Miller-Rabin算法Python实现如下: ``` import random def is_prime(n, k=50): """判断n是否为质数,k为测试因子个数""" if n <= 3: return n == 2 or n == 3 r, d = 0, n - 1 while d % 2 == 0: r += 1 d //= 2 for _ in range(k): a = random.randrange(2, n - 2) x = pow(a, d, n) if x == 1 or x == n - 1: continue for _ in range(r - 1): x = pow(x, 2, n) if x == n - 1: break else: return False return True ``` 代码中的is_prime函数接收两个参数:n表示待判断的数字,k表示测试因子的个数。首先判断n是否小于等于3,如果是则判断该数是否为2或3。如果n大于3,就将n-1写成2^r * d的形式。然后对于每个测试因子a,计算a^d mod n的值,如果等于1或n-1,则判断下一个测试因子。如果不是,则连续进行r-1次平方计算,判断中间是否出现了x^2 ≡ 1 mod n的情况。如果出现则n是合数,否则n有很大可能是质数。 总之,Miller-Rabin算法可以高效地判断一个数是否为质数,主要思想是利用随机选择的测试因子进行判断,并重复多次,以提高判断的准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值