记一次使用快速幂与Miller-Rabin的大素数生成算法

时间:2023-03-09 12:54:25
记一次使用快速幂与Miller-Rabin的大素数生成算法

大家都知道RSA的加密的安全性就是能够找到一个合适的大素数,而现在判断大素数的办法有许多,比如Fermat素性测试或者Miller-Rabin素性测试,而这里我用了Miller-Rabin素性测试的算法,具体的理论我写到下面。

算法的理论基础:

  1. Fermat定理:若n是奇素数,a是任意正整数(1≤ a≤ n−1),则 a^(n-1) ≡ 1 mod n。

2.  如果n是一个奇素数,将n−1表示成2^s*r的形式,r是奇数,a与n是互素的任何随机整数,那么a^r ≡ 1 mod n或者对某个j (0 ≤ j≤ s−1, j∈Z) 等式a^(2jr) ≡ −1 mod n 成立。

实验需要根据这个算法的理论来实现对素数的判定功能,而我将上述理论用C++的 形式写了出来,然后在一些细节的算法上少做润色,成功实现了对素数的生成和判定。

一、实验代码:

#include<iostream>

#include<cmath>

#include<ctime>

#include<cstdlib>

using namespace std;

typedef unsigned long long ll;

long long q_mul( long long a, long long b, long long mod )

{

long long ans = 0;

while(b)

{

if(b & 1)

{

b--;

ans =(ans+ a)%mod;

}

b /= 2;

a = (a + a) % mod;

}

return ans;

}

long long q_pow( long long a, long long b, long long mod )

{

long long ans = 1;

while(b)

{

if(b & 1)

{

ans = q_mul( ans, a, mod );

}

b /= 2;

a = q_mul( a, a, mod );

}

return ans;

}

//long long q_pow(ll a,ll b,ll mod){

// ll base=a;

// ll ans = 1;

// while(b!=0){

// if(b&1) ans = (ans*base)%mod;

// base = (base*base)%mod;

// b>>=1;

// }

// return ans;

//}

int Miller_Rabin(ll n) {

if(n<2) return 0;

if(n==2) return 1;

ll k=0,q=n-1;

while(q%2==0){

q=q/2;

k++;

}

ll a = rand(); //要保证a在(1,n-1)之间,开区间

a=(a%(n-2))+2;

ll result1 = q_pow(a,q,n);

if(result1 == 1||result1 == n-1){

return 1;

}

while(k--){

result1 = q_mul(result1,2,n);

if(result1 == n-1) return 1;

}

return 0;

}

bool True_Miller_Rabin(ll n){

int times = 10;

while(times){

times--;

if(Miller_Rabin(n)==0) return false;

}

return true;

}

int main()

{

srand((unsigned)time(NULL));

ll num;

// while(1){

// cin>>num;

// if(Miller_Rabin(num)==1)

// cout<<"为素数"<<endl;

// else{

// cout<<"是合数"<<endl;

// }

// }

for(ll i=1000000;i<=1005000;i++){

int a =0;

if(True_Miller_Rabin(i)){

cout<< i<<"是素数"<<endl;

}

}

return 0;

}

二、实验结果(自行测试)

这是对1000000000000000000到1000000000000005000里所有素数判定的结果

这是对输入素数的判读

以上结果说明,该程序完全能够胜任在long long类型范围下的素数判定任务。

三、实验总结

本次实验采用了Miller-Rabin算法,而在理解算法的基础上我们要灵活运用。在算法中我最开始用到了C++函数里面的pow函数,然而这个函数导致我素数输出不完整,经过很久的调试,我发现是C++自带库里面的数据类型与long long类型有出入,所以我放弃了使用自带的函数库。之后,我选择了快速幂算法。这个算法比pow函数效果更好,能够对大数进行快速的幂计算。然而在快速幂计算的过程中设计到两个数相乘,当两个Long 类型的数据相乘时会溢出从而导致计算的大素数长度有限。于是我有考虑将幂计算里面的乘法分成若干个加法去进行运算,于是我采用了快速乘与快速幂想结合的方式,也就是我上述代码中绿色的部分(蓝色部分为单纯快速幂),由此我讲幂运算的速度有提升了一个档次,在此基础上也增大了计算素数的范围。

——————Made By Pinging、、、、、hhh  Welcome to CUMT。。。