Miller-Rabin概率素数测试法

目前来说,一般产生大素数的方法有两种:一种是概率素数测试法,另一种是确定性素数测试法。现已有许多种概率素数测试法,如Solovay-Strassen测试法、Lehman测试法及Miller_Rabin测试法等。这些算法基本上是以费尔马定理(Fermat Theorem)为基础,即:若N为素数,则对任意的整数a,0<a<N,必定满足a^(N-1) mod N =1 ,或a^((N-1)/2) mod N =±1 。

 

若N不满足上述条件,则N必为合数。但满足上述条件的N是否一定为素数?事实上并不尽然,还是有少许合数满足这些条件,这些合数称为假素数。但进一步判断,就可以以很高的概率得到素数。

一、Miller_Rabin测试法描述

设N>2且N是奇数,令N-1=(2^s)t,其中s≥1,且t为奇数。如果N是素数,则一定有a^(N-1) mod N =1 。

则下面的s+1个等式中必定满足一个:

a^t (mod N) =1

a^((2^i)t) (mod N)=-1 , i=0,1,2...,s-1

也就是说,如果N是素数,对任意选择的a∈{2,3,..,N-2},必定会使上面s+1个等式中的一个成立。而如果对选择的a∈{2,3,..,N-2},上面的s+1个等式均不成立,则一定可以判定N不是素数。根据此结果,Rabin引入了如下的素数集:

PN={a∈ZN:a^t mod N ≠1且∀i<s ,a^((2^i)t) (mod N)≠-1}

Rabin算法:

1. 任取一个大奇数N。

2. 任取一正整数a∈{2,3,..,N-2}。

3. 如果gcd(a,N)=1且a∉PN,则称N通过一次测试,即N有可能是素数;否则,N必定为合数。

4. 重复上述步骤2、3,任意选择不同的a共k次,以进行测试。

    

    在实际运用中,可首先用300-500个小素数对N进行测试,以提高测试通过的概率和算法的速度。

二、代码实现如下

 

#include <iostream>
#include<string>
#include<cctype>
#include<assert.h>
#include<algorithm>
#include<ctime>
#include<cmath>

using namespace std;
long long mod_fast(long long a,long long b,long long p)
{
    long long aa=a,t=1;
    while(b!=0)
    {
        if(b&1)//是b和1做二进制的且运算 即看b的最后边那一位是不是1,是1的话 返回1  否则返回0

        {
            t=(t%p)*(aa%p)%p;
        }
        aa=(aa%p)*(aa%p)%p;
        b=b/2;//aa平方模
    }
    return t%p;
}
//Miller_Rabin算法
bool Miller_Rabin(long long n)
{
    long long a,s=0,num;
    long long t=n-1,mm=n-1;
    while(!(t & 1))//判断t是否为奇数,否则右移一位,相当于除2
    {
        t=t >> 1 ; //右移一位
        s++;//2的s次方
    }
    srand((unsigned)time(0));//设置随机数种子
    a=rand();//获取随机数a
    num=mod_fast(a,t,n);
    //判断第一个式子a^t mod n=1
    if(num==1){
        return true;
    }
    //进行s次判断
    for(int i=0;i<s;i++)
    {
        if(num==mm)return true;
        else num=mod_fast(num,2,n);
    }
    return false;
}

int main()
{
    long long n;
    bool flag=true;
    srand((unsigned)time(0));//设置随机数种子
    n=rand();//获取随机数n
    //保证n为素数
    if(!(n&1))
    {
        n=n+1;
    }
    while(flag)
    {
        //利用Miller_Robin算法检测
        if(Miller_Rabin(n))
        {
            flag=false;
            cout<<n<<"通过Miller_Robin算法检测!"<<endl;
        }else{
            n=n+2;//不通过n加2继续检测
        }
    }
  return 0;
}

三、运行结果

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,这里给出 Python 的实现代码,分别使用了三种方法来判断奇素数的素性。 ```python import random # 试除法判断素数 def is_prime_trial_division(n): if n < 2: return False for i in range(2, int(n**0.5)+1): if n % i == 0: return False return True # Fermat测试判断素数 def is_prime_fermat(n, k=5): if n < 2: return False if n == 2 or n == 3: return True for _ in range(k): a = random.randint(2, n-2) if pow(a, n-1, n) != 1: return False return True # Solovay-Strassen测试判断素数 def legendre(a, p): if pow(a, (p-1)//2, p) == p-1: return -1 else: return pow(a, (p-1)//2, p) def is_prime_solovay_strassen(n, k=5): if n < 2: return False if n == 2 or n == 3: return True for _ in range(k): a = random.randint(2, n-2) x = pow(a, (n-1)//2, n) if x != 1 and x != n-1 and legendre(a, n) != x: return False return True # Miller-Rabin测试判断素数 def is_prime_miller_rabin(n, k=5): if n < 2: return False if n == 2 or n == 3: return True s, d = 0, 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 # 测试代码 n = int(input("请输入一个奇素数:")) if is_prime_trial_division(n): print(n, "是素数") else: print(n, "不是素数") if is_prime_fermat(n): print(n, "是素数") else: print(n, "不是素数") if is_prime_solovay_strassen(n): print(n, "是素数") else: print(n, "不是素数") if is_prime_miller_rabin(n): print(n, "是素数") else: print(n, "不是素数") ``` 在程序中,`is_prime_trial_division` 函数使用了试除法来判断素数,`is_prime_fermat` 函数使用了 Fermat 测试,`is_prime_solovay_strassen` 函数使用了 Solovay-Strassen 测试,`is_prime_miller_rabin` 函数使用了 Miller-Rabin 测试。在测试时,可以指定测试的次数,这里默认为 5 次。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我的书包哪里去了

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

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

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

打赏作者

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

抵扣说明:

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

余额充值