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




        今天看了《算法竞赛和入门基础》中的大整数类后,我自己也试着去实现一个大整数类,并且完成了整数的四则运算和逻辑运算功能。学习到了很多东西。在此分享一下。代码是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;
    }
};

    全部贴出来是因为我太懒了,见谅啊。
    大整数类除了这个实现,如果大家还有其他实现方法,不妨也分享一下,这里写出来只是抛砖引玉。
    参考书籍:《算法竞赛和入门经典》。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值