大整數類的四則運算和邏輯運算




        今天看了《算法競賽和入門基礎》中的大整數類後,我自己也試着去實現一個大整數類,並且完成了整數的四則運算和邏輯運算功能。學習到了很多東西。在此分享一下。代碼是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;
    }
};

    全部貼出來是因爲我太懶了,見諒啊。
    大整數類除了這個實現,如果大家還有其他實現方法,不妨也分享一下,這裏寫出來只是拋磚引玉。
    參考書籍:《算法競賽和入門經典》。
發佈了39 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章