C++实现大整数运算包(加、减、乘、除、幂模、GCD、乘法逆)

时间:2025-01-26 08:27:29

1.问题描述

大整数运算是现代密码学算法实现的基础,重要性不言而喻。大整数我们指的是二进制位512、1024和2048的数,一般的语言不支持。

2.基本要求

以类库头文件的形式实现。

3.实现提示

   在选择了大整数的存储结构之后,主要实现以下运算:

① 模加;

② 模减;

③ 模乘;

④ 模整除;

⑤ 模取余。这五种运算模拟手算实现。

⑥ 幂模:利用“平方-乘法”算法实现。

⑦ GCD:利用欧几里得算法实现。

⑧ 乘法逆: 利用扩展的欧几里得算法实现。

⑨ 素数判定与生成:概率性素数产生方法产生的数仅仅是伪素数,其缺点在于,尽管其产生合数的可能性很小,但是这种可能性仍然存在:其优点是产生的伪素数没有规律性,而且产生的速度也比较快。此类方法是生成大素数的主要方法,其中较著名的算法有:Miller Rabin算法、Solovay-Strassen算法等。本文讨论Miller  Rabin算法。

Miller Rabin素性测试法是在实际中应用非常广的一种素性测试方案,可以用来判定某随机数是否为素数。其定义如下:

设n>2是一个奇数,设n-1=2sm,其中s是非负整数,m>0是奇数,设0<b<n,如果

bm≡-1(mod n),

或者存在一个r,0≤r<s,使得

b 2^r m≡-1(modn)

则称n通过以b为基的Miller-Rabin测试。

可以利用Miller-Rabin素性测试算法来随机生成大素数,随即生成一个奇数n>2,随即均匀的选取序列b1,b2...,bk∈{1,2,...,n-1},对n进行k次Miller-Rabin素性测试,如果每次输出都为“n可能是素数”,则n是合数的概率小于 1/4k当k足够大时,1/4k是一个十分小的数。

    同学们在具体实现时,为了提高速度最好以空间换时间,在主程序运行前先构造一个大素数表。

 

 

代码如下:

#include <iostream>
#include <string>
#include <cstdlib>
#include <algorithm>//reverse函数所需添加的头文件
using namespace std;
/*
大整数类
*/
class BigInt
{
private:
    inline int compare(string s1, string s2)
    {
        if(() < ())
            return -1;
        else if(() > ())
            return 1;
        else
            return (s2);
    }
public:
    bool flag;//true表示正数,false表示负数,0默认为正数
    string values;//保存所有位上的数字
    BigInt():values("0"),flag(true){};//构造函数
    BigInt(string str)//类型转换构造函数(默认为正整数)
    {
        values = str;
        flag = true;
    }
public:
    friend ostream& operator << (ostream& os, const BigInt& bigInt);//重载输出操作符
    friend istream& operator>>(istream& is, BigInt& bigInt);//输入操作符重载
    BigInt operator+(const BigInt& rhs);//加法操作重载
    BigInt operator-(const BigInt& rhs);//减法操作重载
    BigInt operator*(const BigInt& rhs);//乘法操作重载
    BigInt operator/(const BigInt& rhs);//除法操作重载
    BigInt operator%(const BigInt& rhs);//求余操作重载
};
/*
重载流提取运算符'>>',输出一个整数
*/
ostream& operator << (ostream& os, const BigInt& bigInt)
{
    if (!)
    {
        os << '-';
    }
    os << ;
    return os;
}
/*
重载流插入运算符'>>',输入一个正整数
*/
istream& operator >> (istream& is, BigInt& bigInt)
{
    string str;
    is >> str;
     = str;
     = true;
    return is;
}
/*
两个正整数相加
*/
BigInt BigInt::operator+(const BigInt& rhs)
{
    BigInt ret;
     = true;//正整数相加恒为正数
    string lvalues(values), rvalues();
    //处理特殊情况
    if (lvalues == "0")
    {
         = rvalues;
        return ret;
    }
    if (rvalues == "0")
    {
         = lvalues;
        return ret;
    }
    //调整s1与s2的长度
    unsigned int i, lsize, rsize;
    lsize = ();
    rsize = ();
    if (lsize < rsize)
    {
        for (i = 0; i < rsize - lsize; i++)//在lvalues左边补零
        {
            lvalues = "0" + lvalues;
        }
    }
    else
    {
        for (i = 0; i < lsize - rsize; i++)//在rvalues左边补零
        {
            rvalues = "0" + rvalues;
        }
    }
    //处理本质情况
    int n1, n2;
    n2 = 0;
    lsize = ();
    string res = "";
    reverse((), ());//颠倒字符串,以方便从低位算起计算
    reverse((), ());
    for (i = 0; i < lsize; i++)
    {
        n1 = (lvalues[i] - '0' + rvalues[i] - '0' + n2) % 10;//n1代表当前位的值
        n2 = (lvalues[i] - '0' + rvalues[i] - '0' + n2) / 10;//n2代表进位
        res = res + char(n1 + '0');
    }

    if (n2 == 1)
    {
        res = res + "1";
    }
    reverse((), ());

     = res;
    return ret;
}
/*
两个正整数相减
*/
BigInt BigInt::operator-(const BigInt& rhs)
{
    BigInt ret;
    string lvalues(values), rvalues();
    //负数减负数
    if(flag==false&&==false)
    {
        string tmp = lvalues;
        lvalues = rvalues;
        rvalues = tmp;
    }
    //负数减正数
    if(flag==false&&==true)
    {
        BigInt res(lvalues);
        ret=res+rhs;
         = false;
        return ret;
    }
    if(flag==true&&==false)
    {
        BigInt rel(lvalues),res();
        ret=rel+res;
         = true;
        return ret;
    }
        //处理特殊情况
    if (rvalues == "0")
    {
         = lvalues;
         = true;
        return ret;
    }
    if (lvalues == "0")
    {
         = rvalues;
         = false;
        return ret;
    }
    //调整s1与s2的长度
    unsigned int i, lsize, rsize;
    lsize = ();
    rsize = ();
    if (lsize < rsize)
    {
        for (i = 0; i < rsize - lsize; i++)//在lvalues左边补零
        {
            lvalues = "0" + lvalues;
        }
    }
    else
    {
        for (i = 0; i < lsize - rsize; i++)//在rvalues左边补零
        {
            rvalues = "0" + rvalues;
        }
    }
    //调整使‘-’号前边的数大于后边的数
    int t = (rvalues);//相等返回0,str1<str2返回负数,str1>str2返回正数
    if (t < 0)
    {
         = false;
        string tmp = lvalues;
        lvalues = rvalues;
        rvalues = tmp;
    }
    else if (t == 0)
    {
         = "0";
         = true;
        return ret;
    }
    else
    {
         = true;
    }
    //处理本质情况
    unsigned int j;
    lsize = ();
    string res = "";
    reverse((), ());//颠倒字符串,以方便从低位算起计算
    reverse((), ());
    for (i = 0; i < lsize; i++)
    {
        if (lvalues[i] < rvalues[i])//不足,向前借一维
        {
            j = 1;
            while(lvalues[i+j] == '0')
            {
                lvalues[i+j] = '9';
                j++;
            }
            lvalues[i+j] -= 1;
            res = res + char(lvalues[i] + ':' - rvalues[i]);
        }
        else
        {
            res = res + char(lvalues[i] - rvalues[i] + '0');
        }
    }
    reverse((), ());
    (0, res.find_first_not_of('0'));//去掉前导零

     = res;
    return ret;
}

/*
两个正整数相乘
*/
BigInt BigInt::operator*(const BigInt& rhs)
{
    BigInt ret;
    string lvalues(values), rvalues();
    //处理0或结果正负
    if (lvalues == "0" || rvalues == "0")
    {
         = "0";
         = true;
        return ret;
    }
    if(flag==false||==false)
    {
        =false;
    }
    //处理特殊情况
    unsigned int lsize, rsize;
    lsize = ();
    rsize = ();
    string temp;
    BigInt res, itemp;
    //让lvalues的长度最长
    if (lvalues < rvalues)
    {
        temp = lvalues;
        lvalues = rvalues;
        rvalues = temp;
        lsize = ();
        rsize = ();
    }
    //处理本质情况
    int i, j, n1, n2, n3, t;
    reverse((), ());//颠倒字符串
    reverse((), ());

    for (i = 0; i < rsize; i++)
    {
        temp = "";
        n1 = n2 = n3 = 0;
        for (j = 0; j < i; j++)
        {
            temp = temp + "0";
        }
        n3 = rvalues[i] - '0';
        for (j = 0; j < lsize; j++)
        {
            t = (n3*(lvalues[j] - '0') + n2);
            n1 = t % 10;//n1记录当前位置的值
            n2 = t / 10;//n2记录进位的值
            temp = temp + char(n1 + '0');
        }
        if (n2)
        {
            temp = temp + char(n2 + '0');
        }
        reverse((), ());
         = temp;
        res = res + itemp;
    }

     = ;
    return ret;
}
/*
两个正整数相除
*/
BigInt BigInt::operator/(const BigInt& rhs)
{
    BigInt ret;
    string lvalues(values), rvalues();
    string quotient;
    string temp;
    //处理特殊情况
    if(rvalues == "0")
    {
         = "error";//输出错误
         = true;
        return ret;
    }
    if(lvalues == "0")
    {
         = "0";
         = true;
        return ret;
    }

    if(compare(lvalues, rvalues) < 0)
    {
         = "0";
         = true;
        return ret;
    }
    else if(compare(lvalues, rvalues) == 0)
    {
         = "1";
         = true;
        return ret;
    }
    else
    {
        //处理本质情况

        unsigned int lsize, rsize;
        lsize = ();
        rsize = ();
        int i;
        if(rsize > 1) (lvalues, 0, rsize-1);
        for(i = rsize - 1; i < lsize; i++)
        {
            temp = temp + lvalues[i];
            //试商
            for(char c = '9'; c >= '0'; c--)
            {
                BigInt t = (BigInt)rvalues * (BigInt)string(1, c);
                BigInt s = (BigInt)temp - t;

                if( == true)
                {
                    temp = ;
                    quotient = quotient + c;
                    break;
                }
            }
        }
    }
    //去除前导零
    (0, quotient.find_first_not_of('0'));
     = quotient;
     = true;
    return ret;
}
/*
两个正整数取余
*/
BigInt BigInt::operator%(const BigInt& rhs)
{
    BigInt ret,kj(values),ki();
    string lvalues(values), rvalues();
    string quotient;
    string temp;
    //处理特殊情况
    if(rvalues == "0")
    {
         = "error";//输出错误
         = true;
        return ret;
    }
    if(lvalues == "0")
    {
         = "0";
         = true;
        return ret;
    }

    if(compare(lvalues, rvalues) < 0)
    {
        if(flag==false)
        {
            =(ki-kj).values;
             = true;
            return ret;
        }else{
             = lvalues;
             = true;
            return ret;
        }
    }
    else if(compare(lvalues, rvalues) == 0)
    {
         = "0";
         = true;
        return ret;
    }
    else
    {
        //处理本质情况
        unsigned int lsize, rsize;
        lsize = ();
        rsize = ();
        int i;
        if(rsize > 1) (lvalues, 0, rsize-1);
        for(i = rsize - 1; i < lsize; i++)
        {
            if(temp=="0"){
                temp=lvalues[i];
            }else{
                temp = temp + lvalues[i];
            }
            //试商
            for(char c = '9'; c >= '0'; c--)
            {
                BigInt t = (BigInt)rvalues * (BigInt)string(1, c);
                BigInt s = (BigInt)temp - t;

                if( == true)
                {
                    //cout<<<<endl;
                    temp = ;
                    quotient = quotient + c;
                    break;
                }
            }
        }
    }
    //去除前导零
    (0, quotient.find_first_not_of('0'));
     = temp;
     = true;
    return ret;
}
/*
一个大整数和一个小整数的取余

int divMod(string ch,int num)
{
    int s=0;
    for(int i=0;ch[i]!='\0';i++)
    s=(s*10+ch[i]-'0')%num;
    return s;
}*/

/*
欧几里德求GCD
*/
BigInt gcd(BigInt a,BigInt b)
{
    BigInt stemp;
    //cout<<a<<endl;
    //cout<<b<<endl;
    if((a-b).flag==false)//判断大小
    {
        =;
        =;
        =;
    }
    if(=="0") return a;
    else return gcd(b,a%b);
}
/*
快速幂
*/
BigInt fast(BigInt a,BigInt b)
{
    BigInt aa=a,t("1"),k("2");
 //   int b2=atoi(b1[lsize-1].c_str());
    while(!="0")
    {
        if((b%k).values!="0")
        {
            t=t*aa;
        }
        aa=aa*aa;
        b=b/k;
    }
    return t;
}
/*
快速幂模
*/
BigInt mod_fast(BigInt a,BigInt b,BigInt p)
{
    BigInt aa=a,t("1"),k("2");
 //   int b2=atoi(b1[lsize-1].c_str());
    while(!="0")
    {
        if((b%k).values!="0")
        {
            t=(t%p)*(aa%p)%p;
        }
        aa=(aa%p)*(aa%p)%p;
        b=b/k;
    }
    return t%p;
}

/*
扩展欧几里德实现乘法逆
*/
BigInt extgcd(BigInt a, BigInt b, BigInt& x, BigInt& y)
{
    BigInt d();

    if( != "0"){
        d = extgcd(b, a % b, y, x);
        y = y-(a / b) * x;
 //   cout<<"a:"<<a<<endl;
  //  cout<<"b:"<<b<<endl;
  //  cout<<"x:"<<x<<endl;
  //  cout<<"y:"<<y<<endl<<endl<<endl;
    }else {
         = "1";
         = "0";
    }
    return d;
}
BigInt mod_inverse(BigInt a, BigInt m)
{
    BigInt x, y;
    extgcd(a, m, x, y);
    if(==false)
    {
        =true;
        x=m-x;
    }
    return (m + x % m) % m;
}

int main()
{
    BigInt a,b,n;
    char op;
    while(1){
        cout<<"请按提示数字进行操作。。。。"<<endl<<endl;
        cout<<"1-------计算(a+b)mod n的值-------"<<endl;
        cout<<"2-------计算(a-b)mod n的值-------"<<endl;
        cout<<"3-------计算(a*b)mod n的值-------"<<endl;
        cout<<"4-------计算(a/b)mod n的值-------"<<endl;
        cout<<"5-------计算(a%b)mod n的值-------"<<endl;
        cout<<"6-------计算(a^b)mod n的值-------"<<endl;
        cout<<"7-------计算 GCD(a,b) 的值-------"<<endl;
        cout<<"8-------计算a和n乘法逆的值-------"<<endl;
        cout<<endl<<endl<<"请输入数字进行计算:";
        cin >> op;
        switch(op)
        {
            case '1':
                cout<<"请输入a、b和n的值:";
                cin>>a>>b>>n;
                cout<<endl;
                cout<<"a+b的值:"<<a+b<<endl;
                cout<<"(a+b)mod n的值: "<< (a+b)%n<<endl<<endl<<endl<<endl;
                break;
            case '2':
                cout<<"请输入a、b和n的值:";
                cin>>a>>b>>n;
                cout<<endl;
                cout<<"a-b的值:"<<a-b<<endl;
                cout<<"(a-b)mod n的值: "<< (a-b)%n<<endl<<endl<<endl<<endl;
                break;
            case '3':
                cout<<"请输入a、b和n的值:";
                cin>>a>>b>>n;
                cout<<endl;
                cout<<"a*b的值:"<<a*b<<endl;
                cout<<"(a*b)mod n的值: "<< (a*b)%n<<endl<<endl<<endl<<endl;
                break;
            case '4':
                cout<<"请输入a、b和n的值:";
                cin>>a>>b>>n;
                cout<<endl;
                cout<<"a/b的值:"<<a/b<<endl;
                cout<<"(a/b)mod n的值: "<< (a/b)%n<<endl<<endl<<endl<<endl;
                break;
            case '5':
                cout<<"请输入a、b和n的值:";
                cin>>a>>b>>n;
                cout<<endl;
                cout<<"a%b的值:"<<a%b<<endl;
                cout<<"(a%b)mod n的值: "<< (a%b)%n<<endl<<endl<<endl<<endl;
                break;
            case '6':
                cout<<"请输入a、b和n的值:";
                cin>>a>>b>>n;
                cout<<endl;
                cout<<"a^b的值:"<<fast(a,b)<<endl;
                cout<<"(a^b)mod n的值: "<<mod_fast(a,b,n)<<endl<<endl<<endl<<endl;
                break;
            case '7':
                cout<<"请输入a和b的值:";
                cin>>a>>b;
                cout<<endl;
                cout<<"GCD(a,b)的值:"<<gcd(a,b)<<endl<<endl<<endl<<endl;
                break;
            case '8':
                cout<<"请输入a和n的值:";
                cin>>a>>n;
                cout<<endl;
                cout<<"a和n的乘法逆: "<< mod_inverse(a,n)<<endl<<endl<<endl<<endl;
                break;
            default:break;
            }
    }
    return 0;
}

Miller-Rabin大素数检测算法请看我的这篇文章 /qq_34490018/article/details/79844036