大數運算_string類的簡單應用

在通過對string類的學習之後,我們就可以通過對string類的使用去模擬大數的運算.

#pragma once
#include<string>
#include<assert.h>
#include<iostream>
using namespace std;
typedef long long INT64;
#define Max_INT64  0x7FFFFFFFFFFFFFFF
#define Min_INT64  0x0000000000000000
class BigData
{
public:
    BigData(INT64 value = 0xCCCCCCCCCCCCCCCC)
        :_value(value)
    {
        INT64TOString();
    }
    BigData(const char*pData)
    {
        if (NULL == pData)
        {
            assert(false);
            return;
        }
        char cSombol = pData[0];
        char *pStr = (char*)pData;
        if (cSombol == '+' || cSombol == '-')
        {
            pStr++;
        }
        else if (cSombol >= '0'&&cSombol <= '9')
        {
            cSombol='+';
        }
        else
        {
            return;
        }//處理符號位
        while (*pStr == '0')
        {
            pStr++;
        }
        _Data.resize(strlen(pData) + 1);
        _Data[0] = cSombol;
        _value = 0;
        int icount = 1;
        while (*pStr >= '0'&&*pStr < '9')
        {
            _value = _value * 10 + (*pStr - '0');
            _Data[icount++] = *pStr;
            pStr++;
        }
        _Data.resize(icount);
        if (cSombol == '-')
        {
            _value = 0 - _value;
        }
    }
    BigData operator + (const BigData& bigdata)
    {
        if (IsInt64OverFlow() && bigdata.IsInt64OverFlow())
        {
            if (_Data[0] != bigdata._Data[0])
            {
                return BigData(_value + bigdata._value);
            }
            else
            {
                INT64 tmp = Min_INT64 - _value;
                if ((_value >= 0 && Max_INT64 - _value >= bigdata._value)
                    || (_value < 0 && tmp <= bigdata._value))
                {
                    return BigData(_value + bigdata._value);
                }
            }
        }
        if (_Data[0] == bigdata._Data[0])
        {
            return BigData(Add(_Data, bigdata._Data).c_str);
        }
        return BigData(Sub(_Data, bigdata._Data).c_str());
    }
    BigData operator - (const BigData& bigdata)
    {
        if (IsInt64OverFlow() && bigdata.IsInt64OverFlow())
        {
            if (_Data[0] == bigdata._Data[0])
            {
                return BigData(_value - bigdata._value);
            }
            else
            {
                if ((_value > 0 && Max_INT64 + bigdata._value >= _value) ||
                    (_value < 0 && Min_INT64 + bigdata._value <= _value))
                {
                    return BigData(_value - bigdata._value);
                }
            }
        }
        if (_Data[0] != bigdata._Data[0])
        {
            return BigData(Add(_Data, bigdata._Data).c_str);
        }
        return BigData(Sub(_Data, bigdata._Data).c_str());
    }
    BigData operator * (const BigData& bigdata)
    {
        //除數不爲0
        if (_value == 0 || bigdata._value == 0)
        {
            return BigData(INT64(0));
        }
        //沒有溢出
        if (IsInt64OverFlow() && bigdata.IsInt64OverFlow())
        {
            //同號
            if (_Data[0] == bigdata._Data[0])
            {
                if ((_value>0 && Max_INT64 / _value >= bigdata._value) ||
                    (_value<0 && Min_INT64 / _value <= bigdata._value))
                {
                    return BigData(_value*bigdata._value);
                }
            }
            //異號
            else
            {
                if ((_value>0 && Max_INT64 / _value <= bigdata._value) ||
                    (_value<0 && Min_INT64 / _value >= bigdata._value))
                {
                    return BigData(_value*bigdata._value);
                }
            }
        }
        return BigData(Mul(_Data, bigdata._Data).c_str());
    }
    BigData operator / (const BigData& bigdata)
    {

        //除數爲零
        if (bigdata._Data[1] == '0')
        {
            assert(false);

        }
        //都沒溢出
        if (IsInt64OverFlow() && bigdata.IsInt64OverFlow())
        {
            return BigData(_value / bigdata._value);
        }
        //被除數小於除數
        if (_Data.size() < bigdata._Data.size() ||                 //123    123445
            (_Data.size() == bigdata._Data.size() &&                //2239   2234
            strcmp(_Data.c_str() + 1, bigdata._Data.c_str() + 1)<0))
        {
            return BigData(INT64(0));
        }
        //
        if (bigdata._Data == "+1" || _Data == "-1")
        {
            std::string ret = _Data;
            if (_Data[0] != bigdata._Data[0])
            {
                ret[0] = '-';
            }
            return BigData(ret.c_str());
        }
        //數值相等
        if (strcmp(_Data.c_str() + 1, bigdata._Data.c_str() + 1) == 0)
        {
            std::string ret = "+1";
            if (_Data[0] != bigdata._Data[0])
            {
                ret[0] = '-';
            }
            return BigData(ret.c_str());
        }
        return BigData(Div(_Data, bigdata._Data).c_str());
    }
    bool IsInt64OverFlow()const
    {
        string tmp("+9223372036854775807");
        if (_Data[0] == '-')
        {
            tmp = "-9223372036854775807";
        }
        if (_Data.size() < tmp.size())
            return true;
        else if (_Data.size() == tmp.size() && (_Data <= tmp))
        {
            return true;
        }
        return false;
    }
    void INT64TOString()
    {
        INT64 tmp = _value;
        char cSymbol = '+';
        if (_value < 0)
        {
            cSymbol = '-';
        }
        _Data.append(1, cSymbol);  //append  追加

        //轉化
        while (tmp)
        {
            int c = tmp % 10;
            if (c < 0)
            {
                c = 0 - c;
            }
            _Data.append(1, c + '0');
            tmp /= 10;
        }
        char *pleft = (char *)_Data.c_str() + 1;
        char *pright = pleft + _Data.size() - 2;
        while (pleft < pright)
        {
            char cTemp = *pleft;
            *pleft++ = *pright;
            *pright-- = cTemp;
        }
    }
    char SubLoop(char*pLeft, int LSize, const char* pRight, int RSize)
    {
        assert(pLeft != NULL && pRight != NULL);
        char cRet = '0';
        while (true)
        {
            //左小於右
            if (!IsLeftStrBig(pLeft, LSize, pRight, RSize))
            {
                break;
            }

            int LDataLen = LSize - 1;
            int RDataLen = RSize - 1;
            //處理循環相減
            while (LDataLen >= 0 && RDataLen >= 0)
            {
                char ret = pLeft[LDataLen] - '0';
                ret -= pRight[RDataLen] - '0';
                if (ret < 0)
                {
                    pLeft[LDataLen - 1] -= 1;
                    ret += 10;
                }
                pLeft[LDataLen] = ret + '0';
                LDataLen--;
                RDataLen--;
            }
            //跳過相減產生的多餘的0
            while (*pLeft == '0' && LSize > 0)
            {
                pLeft++;
                LSize--;
            }
            cRet++;
        }
        return cRet;
    }
    friend ostream & operator<<(ostream&out, const BigData&bdata);
    string Add(std::string left, std::string right)
    {
        int iLSize = left.size();
        int iRSize = right.size();
        if (iLSize < iRSize)
        {
            std::swap(left, right);  //長的放在左邊
            std::swap(iLSize, iRSize);
        }
        std::string sRet;
        sRet.resize(iLSize + 1);  //最高位可能有進位
        sRet[0] = left[0];
        char step = 0;     //記錄進位

        for (int iIdx = 1; iIdx < iLSize; iIdx++)
        {
            char cRet = left[iLSize - iIdx] - '0' + step;
            if (iIdx < iRSize)
            {
                cRet += (right[iRSize - iIdx] - '0');
            }
            sRet[iLSize - iIdx + 1] = cRet % 10 + '0';
            step = cRet / 10;
        }

        sRet[1] = step + '0';   //最高位的進位
        return sRet;
    }
    string Sub(std::string left, std::string right)
    {
        int iLSize = left.size();
        int iRSize = right.size();
        char cSymbol = left[0];
        if (iLSize < iRSize ||
            iLSize == iRSize&&
            left < right)
        {
            std::swap(left, right);
            std::swap(iLSize, iRSize);
            if (cSymbol == '+')
            {
                cSymbol = '-';
            }
            else
            {
                cSymbol = '+';
            }
        }

        std::string strRet;     //保存結果
        strRet.resize(left.size());
        strRet[0] = cSymbol;
        //從低往高,取left的每一位
        //從低往高,取right的每一位
        for (int Idx = 1; Idx < iLSize; Idx++)
        {
            char cRet = left[iLSize - Idx] - '0';
            if (Idx < iRSize)
            {
                cRet -= (right[iRSize - Idx] - '0');
            }

            //判斷是否借位
            if (cRet < 0)
            {
                left[iLSize - Idx - 1] -= 1;
                cRet += 10;
            }
            strRet[iLSize - Idx] = cRet + '0';
        }
        return strRet;
    }
    string Mul(std::string left, std::string right)
    {
        //確定符號位
        char cSymbol = '+';
        if (left[0] != right[0])
        {
            cSymbol = '-';
        }

        int iLSize = left.size();
        int iRSize = right.size();
        if (iLSize > iRSize)
        {
            std::swap(left, right);
            std::swap(iLSize, iRSize);
        }

        std::string sRet;
        sRet.assign(iLSize + iRSize - 1, '0');
        sRet[0] = cSymbol;
        int iDataLen = sRet.size();
        int ioffset = 0;  //記錄偏移量

        //取左邊一位,與右邊的每一位相乘
        for (int iLIdx = 1; iLIdx < iLSize; ++iLIdx)
        {
            char cLeft = left[iLSize - iLIdx] - '0';
            char cStep = 0;
            if (cLeft == 0)
            {
                ioffset++;
                continue;
            }

            for (int iRIdx = 1; iRIdx < iRSize; ++iRIdx)
            {
                char cRet = cLeft*(right[iRSize - iRIdx] - '0') + cStep;
                cRet += sRet[iDataLen - iRIdx - ioffset] - '0';
                sRet[iDataLen - iRIdx - ioffset] = (cRet % 10) + '0';
                cStep = cRet / 10;
            }
            sRet[iDataLen - iRSize - ioffset] += cStep;
            ioffset++;
        }
        return sRet;
    }
    string Div(std::string left, std::string right)
    {
        std::string sRet;
        //符號位
        sRet.append(1, '+');
        if (left[0] != right[0])
        {
            sRet[0] = '-';
        }

        char* pLeft = (char *)(left.c_str() + 1);
        char* pRight = (char *)(right.c_str() + 1);
        int LSize = left.size() - 1;
        int DataLen = right.size() - 1;

        for (int iIdx = 0; iIdx < LSize;)
        {
            //處理被除數中的0
            if (*pLeft == '0')
            {
                sRet.append(1, '0');
                pLeft++;
                iIdx++;
                continue;
            }

            if (!IsLeftStrBig(pLeft, DataLen, pRight, right.size() - 1))
            {
                sRet.append(1, '0');
                DataLen++;
                if (DataLen + iIdx > LSize)
                {
                    break;
                }
            }
            else
            {
                sRet.append(1, SubLoop(pLeft, DataLen, pRight, right.size() - 1));
                while (*pLeft == '0' && DataLen > 0)
                {
                    pLeft++;
                    iIdx++;
                    DataLen--;
                }
                DataLen++;
                if (DataLen + iIdx > LSize)
                {
                    break;
                }
            }
        }
        return sRet;
    }
    bool BigData::IsLeftStrBig(const char* pLeft, int LSize, const char * pRight, int RSize)
    {
        if (LSize > RSize ||
            LSize == RSize && strcmp(pLeft, pRight) >= 0)
        {
            return true;
        }
        return false;
    }
    ostream& operator<<(std::ostream& _cout)
    {
        if (IsInt64OverFlow())
        {
            _cout << _value << std::endl;
        }
        else
        {
            char* pData = (char *)_Data.c_str();
            if ('+' == pData[0])
            {
                pData++;
            }
            _cout << pData << std::endl;
        }
        return _cout;
    }
private:
    string _Data;//大
    INT64 _value;//小    
};
void test1()    //測試加法
{
    //BigData b1(23456);
    //BigData b2("23456");
    //BigData b3("+23456");
    //BigData b4("+23456dfg");
    //BigData b5("-23456");
    //BigData b6("       ");
    //BigData b7("000000023456");

    //cout << b1 << endl;
    //cout << b2 << endl;
    //cout << b3 << endl;
    //cout << b4 << endl;
    //cout << b5 << endl;
    //cout << b6 << endl;
    //cout << b7 << endl;

    /*BigData left(36789);
    BigData right(23761);
    cout << left + right << endl;*/


    /*BigData left(9223372036854775807);
    BigData right(2);
    cout << left + right << endl;*/

    /*BigData left1("-9223372036854775808");
    BigData right1("-3");
    cout << left1 + right1 << endl;*/

    BigData left("99999999999999999999999999999999");
    BigData right("11111111111111111111111111111111");
    cout << left + right << endl;
}

void test2()      //測試減法
{
    /*BigData left(56789);
    BigData right(25323);
    cout << left - right << endl;*/

    /*BigData left(9223372036854775807);
    BigData right(999);
    cout << left - right << endl;*/

    /*BigData left("111111111111111111111111111111111111111");
    BigData right("99");
    cout << left - right << endl;*/

    /*BigData left(9223372036854775807);
    BigData right(-999);
    cout << left - right << endl;*/

    /*BigData left("-9223372036854775808");
    BigData right("999");
    cout << left - right << endl;*/

    BigData left("-9223372036854775809");
    BigData right("-999");
    cout << left - right << endl;
}

void test3()     //測試乘法
{
    /*BigData left("99");
    BigData right("999999999999999999999999999999999");
    cout << left*right << endl;*/

    //BigData left(99999);
    //BigData right(99);
    //cout << left*right << endl;

    /*BigData left("99");
    BigData right("-999999999999999999999999999999999");
    cout << left*right << endl;*/

    BigData left(-99);
    BigData right(99999);
    cout << left*right << endl;
}

void test4()      //測試除法
{
    /*BigData left(99999);
    BigData right(99999);
    cout << left/right << endl;*/

    /*BigData left("222222222222222222222222222222");
    BigData right("33");
    cout << left / right << endl;*/

    /*BigData left(-999990000000000);
    BigData right(99999);
    cout << left / right << endl;*/

    BigData left(678789);
    BigData right(99999135547);
    cout << left / right << endl;
}

int main()
{
    //test1();
    //test2();
    //test3();
    test4();
    system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章