大整数类的四则运算和逻辑运算

来源:互联网 发布:javascript 引号 转义 编辑:程序博客网 时间:2024/05/02 08:47



        今天看了《算法竞赛和入门基础》中的大整数类后,我自己也试着去实现一个大整数类,并且完成了整数的四则运算和逻辑运算功能。学习到了很多东西。在此分享一下。代码是C++的。用了C++中的STL模板类vector。

        大整数类的数据存储结构如下所示:

        static const int BASE=100000000;
        static const int WIDTH=8;
        std::vector<int> s;

        下面我在书里原有的基础上继续编写了乘除和减法的代码。

class BigInteger{public:
    //数据存储结构    static const int BASE=100000000;    static const int WIDTH=8;    std::vector<int> s;
    //构造函数    BigInteger(long long num=0)    {        *this=num;    }
    //long long型整数赋值方法    BigInteger operator = (long long num)    {        s.clear();        do{            s.push_back(num%BASE);            num/=BASE;        }while(num);        return *this;    }
    //string类型赋值方法    BigInteger operator = (const std::string &str)    {        s.clear();        int x,len=(str.length()-1)/WIDTH+1;        for(int i=0;i<len;i++)        {
            //从尾部开始切割            int end=str.length()-i*WIDTH;            int start=std::max(0,end-WIDTH);
            //用sscnaf会去除前导零,下面输出的时候要注意,不过书里代码都已经给出了,这里我代为说明一下。            sscanf(str.substr(start,end-start).c_str(),"%d",&x);            s.push_back(x);        }        return *this;    }
    //加法    BigInteger operator + (const BigInteger& b) const    {        BigInteger c;        c.s.clear();        for(int i=0,g=0;;i++)        {            if(g==0&&i>=s.size()&&i>=b.s.size())                break;            int x=g;            if(i<s.size())                x+=s[i];            if(i<b.s.size())                x+=b.s[i];            c.s.push_back(x%BASE);            g=x/BASE;        }        return c;    }    BigInteger operator += (const BigInteger& b)    {        *this=*this+b;        return *this;    }
    //仿照加法写的减法,需要注意的是只需在最前面加负号    BigInteger operator - (const BigInteger& b) const    {        BigInteger c;        c.s.clear();        int MAX=std::max(s.size(),b.s.size());        for(int i=0,g=0;;i++)        {            if(g==0&&i>=MAX)                break;            int x=g;            if(i<s.size())                x+=s[i];            if(i<b.s.size())                x-=b.s[i];
            //!!!!!!            if(i==MAX-1)                c.s.push_back(x%BASE);            else                c.s.push_back(abs(x%BASE));            //!!!!!!
            g=x/BASE;        }        return c;    }    BigInteger operator -= (const BigInteger& b)    {        *this=*this-b;        return *this;    }    //自己写的,效率有点低,我把vector中的数全部转化为一个整体的string类型,再进行乘法操作,这是我最先想到的写法。    BigInteger operator * (const BigInteger& b)    {        std::stringstream ss;        for(int i=s.size()-1;i>=0;i--)            ss<<s[i];        std::string operand1=ss.str();        ss.str("");        for(int i=b.s.size()-1;i>=0;i--)            ss<<b.s[i];        std::string operand2=ss.str();
        //将string中的一个个数转为int型的数        std::vector<int> c,d,temp;        for(int i=operand1.length()-1;i>=0;i--)            c.push_back(operand1[i]-'0');        for(int i=operand2.length()-1;i>=0;i--)            d.push_back(operand2[i]-'0');        int MAX=std::max(c.size(),d.size());        for(int i=0;i<MAX*2+1;i++)            temp.push_back(0);        for(int i=0;i<c.size();i++)            for(int j=0;j<d.size();j++)                temp[i+j]+=c[i]*d[j];        for(int i=0;i<2*MAX+1;i++)            if(temp[i]>9)            {                temp[i+1]+=temp[i]/10;                temp[i]%=10;            }        int m=2*MAX;        while(temp[m]==0)            m--;        BigInteger another;        another.s.clear();        int len=(m-1)/WIDTH+1;        for(int i=0;i<len;i++)            another.s.push_back(0);        for(int i=0;i<len;i++)        {            int x=1;            int k=0;            int end=std::min(m+1,(i+1)*WIDTH);            int start=i*WIDTH;            for(int j=start;j<end;j++)            {                k+=x*temp[j];                x*=10;            }            another.s[i]=k;        }        return another;    }    BigInteger operator *= (const BigInteger& b)    {        *this=*this*b;        return *this;    }
    //自己写的除法,可以实现像int型一样的效果    BigInteger operator / (const BigInteger& b)    {        std::string operand1,operand2,result;        std::stringstream ss;        for(int i=s.size()-1;i>=0;i--)            ss<<s[i];        operand1=ss.str();        ss.str("");        for(int i=b.s.size()-1;i>=0;i--)            ss<<b.s[i];        operand2=ss.str();        int len1,len2;        len1=operand1.length();        len2=operand2.length();        if(len1<len2)   //若操作数1小于操作数2,返回0            return 0;        if(*this==b)    //若两数相等,返回1,这里用到下面的“==”重载运算符            return 1;        std::vector<int> c,d;        for(int i=0;i<len1;i++)        {            c.push_back(operand1[i]-'0');            if(i<len2)                d.push_back(operand2[i]-'0');            else                d.push_back(0);        }        int time=len1-len2;        int len=len1;        int k,l=0;        for(int i=0;i<=time;i++)        {            int ok=1;            k=0;            do{                if(c[l]==0)                {                    l++;                    ok=0;                    len1--;                }                if(len==len1)                {                    int j=0;                    while(j<len2)                    {                        if(c[i+j]>d[j])    //第一次大就表示operand1 > operand2                        {                            ok=1;                            break;                        }                        else if(c[i+j]<d[j])       //第一次小就表示operand1 < operand2                        {                            ok=0;                            break;                        }                        j++;                    }                }                if(ok)                {                    for(int j=0;j<len;j++)                    {                        c[j+i]-=d[j];                        if(c[j+i]<0)                        {                            c[j+i-1]--;                            c[j+i]+=10;                        }                    }                    k++;                }            }while(ok);            len--;            result+=k+'0';        }        BigInteger temp;        temp=result;        return temp;    }    BigInteger operator /= (const BigInteger& b)    {        *this=*this/b;        return *this;    }
    //以下的重载方法全都在上面的四则运算上编写,不再介绍    BigInteger operator % (const BigInteger& b)    {        BigInteger c;        c=*this-(*this/b)*b;        return c;    }    BigInteger operator %= (const BigInteger& b)    {        *this=*this%b;        return *this;    }    bool operator < (const BigInteger& b) const    {        if(s.size()!=b.s.size())            return s.size()<b.s.size();        for(int i=s.size()-1;i>=0;i--)            if(s[i]!=b.s[i])                return  s[i]<b.s[i];        return false;    }    bool operator > (const BigInteger& b) const    {        return b<*this;    }    bool operator <= (const BigInteger& b) const    {        return !(b<*this);    }    bool operator >= (const BigInteger& b) const    {        return !(*this<b);    }    bool operator != (const BigInteger& b) const    {        return *this<b||*this>b;    }    bool operator == (const BigInteger& b) const    {        return !(*this<b)&&!(*this>b);    }    friend std::ostream& operator << (std::ostream& out,const BigInteger& x)    {        out<<x.s.back();        for(int i=x.s.size()-2;i>=0;i--)        {            char buf[20];            sprintf(buf,"%08d",x.s[i]);            for(int j=0;j<strlen(buf);j++)                out<<buf[j];        }        return out;    }    friend std::istream& operator >> (std::istream& in,BigInteger& x)    {        std::string s;        if(!(in>>s))            return in;        x=s;        return in;    }};
    全部贴出来是因为我太懒了,见谅啊。
    大整数类除了这个实现,如果大家还有其他实现方法,不妨也分享一下,这里写出来只是抛砖引玉。
    参考书籍:《算法竞赛和入门经典》。

2 0
原创粉丝点击