zoukankan      html  css  js  c++  java
  • 记一次使用快速幂与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在(1n-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;

    }

       

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

     

    这是对10000000000000000001000000000000005000里所有素数判定的结果

    这是对输入素数的判读

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

    三、实验总结

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

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

    因为菜,所以仍在努力。
  • 相关阅读:
    Maven教程
    Logback文件这么配置,TPS提高至少10倍
    查看ElasticSearch服务状态和结果的URL
    no main manifest attribute, in demo-1.0.jar
    Rocketmq原理&最佳实践
    【ORACLE】Oracle提高篇之DECODE
    ZooKeeper架构原理你学会了吗?
    01:kubernetes概述
    08:图形页面管理监控
    07:企业级镜像仓库Harbor
  • 原文地址:https://www.cnblogs.com/Pinging/p/7468539.html
Copyright © 2011-2022 走看看