数字字符串四则运算


string版本

#include <stdio.h>
#include <string>

#define ASSERT(b) \
    printf("%s : %s\n", #b, b ? "OK" : "Fail");

using namespace std;

class CNumber
{
    enum AlignZeroFlag
    {
        ALIGN_ZERO_LEFT, //对齐时左侧填充0
        ALIGN_ZERO_RIGHT //对齐时右侧填充0
    };

public:
    //数字字符顺序 123456 => CNumber m_strNum[0] = '1'

    CNumber() : m_strNum("0")
    {

    }

    CNumber(const char *num) : m_strNum(num)
    {
        FormtNumStr(m_strNum);
    }

    CNumber(const int num)
    {
        Num2Str(num, m_strNum);
    }

    CNumber(const CNumber &other)
    {
        m_strNum = other.m_strNum;
    }

    CNumber& operator=(const CNumber &rhs)
    {
        if (this != &rhs)
        {
            m_strNum = rhs.m_strNum;
        }

        return *this;
    }

    bool IsNegative() const
    {
        return IsNegative(m_strNum);
    }

    bool IsZero() const
    {
        return m_strNum[0] == '0';
    }

    //abs(CNumber)
    CNumber abs(const CNumber &other)
    {
        CNumber num(other);

        if (num.IsNegative()) num *= -1;

        return num;
    }

    //++CNumber
    CNumber& operator++()
    {
        return operator+=(1);
    }

    //CNumber++
    CNumber operator++(const int)
    {
        CNumber numRet = *this;

        operator+=(1);

        return numRet;
    }

    //--CNumber
    CNumber& operator--()
    {
        return operator-=(1);
    }

    //CNumber--
    CNumber operator--(const int)
    {
        CNumber numRet = *this;

        operator-=(1);

        return numRet;
    }

    //CNumber > CNumber
    bool operator>(const CNumber &rhs) const
    {
        return gt(m_strNum, rhs.m_strNum);  
    }

    //CNumber < CNumber
    bool operator<(const CNumber &rhs) const
    {
        return !(operator>(rhs));
    }

    //CNumber == CNumber
    bool operator==(const CNumber &rhs) const
    {       
        return eq(m_strNum, rhs.m_strNum);
    }

    //CNumber + CNumber
    friend CNumber operator+(const CNumber &lhs, const CNumber &rhs);

    //CNumber += CNumber;
    CNumber& operator+=(const CNumber &rhs)
    {
        m_strNum = Add(m_strNum, rhs.m_strNum);

        return *this;
    }

    //CNumber - CNumber
    friend CNumber operator-(const CNumber &lhs, const CNumber &rhs);

    //CNumber -= CNumber;
    CNumber& operator-=(const CNumber &rhs)
    {
        if (*this == rhs)
        {
            m_strNum = "0";
            return *this;
        }

        m_strNum = Subtract(m_strNum, rhs.m_strNum);

        return *this;
    }

    //CNumber * CNumber
    friend CNumber operator*(const CNumber &lhs, const CNumber &rhs);

    //CNumber *= CNumber;
    CNumber& operator*=(const CNumber &rhs)
    {
        m_strNum = Multiply(m_strNum, rhs.m_strNum);

        return *this;
    }

    //CNumber / CNumber
    friend CNumber operator/(const CNumber &lhs, const CNumber &rhs);

    //CNumber /= CNumber;
    CNumber& operator/=(const CNumber &rhs)
    {
        string strNumRemainder;

        m_strNum = Divide(m_strNum, rhs.m_strNum, strNumRemainder);

        return *this;
    }

    //CNumber % CNumber
    friend CNumber operator%(const CNumber &lhs, const CNumber &rhs);
    //CNumber %= CNumber;
    CNumber& operator%=(const CNumber &rhs)
    {
        Divide(m_strNum, rhs.m_strNum, m_strNum); 
        return *this;
    }


public:
    //数字转换为字符串
    static void Num2Str(int n, string &strNum)
    {
        if (n == 0)
        {
            strNum = "0";
            return;
        }

        char    cSign = 0;
        strNum.clear();

        if (n < 0)
        {
            cSign = '-';
            n = -n;
        }

        while (n > 0)
        {
            strNum.insert(strNum.begin(), char((n%10) + '0'));

            n /= 10;
        }

        if (cSign)
        {
            strNum.insert(strNum.begin(), cSign);
        }
    }


    //负数判定
    static bool IsNegative(const string &num)
    {
        if (0 == num.size()) return false;
        return (num[0] == '-');
    }

    //零判定
    static bool IsZero(const string &num)
    {
        if (0 == num.size()) return true;
        return num[0] == '0';
    }

    //去除数字前面的'+'号及'0'字符
    static void FormtNumStr(string &strNum)
    {
        switch (strNum.size())
        {
        case 0:
            //"" => "0"
            strNum = "0";
            return;
        case 1:
            {
                //"-" or "+" => "0"
                if (('-' == strNum[0]) || ('+' == strNum[0]))
                {
                    strNum = "0";
                    return;
                }
            }
            break;
        }

        //+5 => 5
        if ('+' == strNum[0])
        {
            strNum.erase(0, 1);
        }

        if ('-' == strNum[0])
        {
            //-0005 => -5
            while (strNum.size() > 2)
            {
                if ('0' != strNum[1]) break;
                strNum.erase(1, 1);
            }
        }
        else
        {
            //0005 => 5
            while (strNum.size() > 1)
            {
                if ('0' != strNum[0]) break;
                strNum.erase(0, 1);
            }
        }
    }

    //对齐数字
    static void AlignNumStr(string &strNum1, string &strNum2, AlignZeroFlag flag)
    {
        FormtNumStr(strNum1);
        FormtNumStr(strNum2);

        size_t nNumOffset1  = strNum1[0] == '-' ? 1 : 0;
        size_t nNumOffset2  = strNum2[0] == '-' ? 1 : 0;
        size_t nNum1Length  = strNum1.size() - nNumOffset1;
        size_t nNum2Length  = strNum2.size() - nNumOffset2;
        size_t nFixCnt      = 0;
        size_t nFixOffset   = 0;
        string *pStrNumToFix= NULL;

        if (nNum1Length == nNum2Length) return;

        if (nNum1Length > nNum2Length)
        {
            nFixCnt         = nNum1Length - nNum2Length;
            nFixOffset      = nNumOffset2;
            pStrNumToFix    = &strNum2;
        }
        else
        {
            nFixCnt         = nNum2Length - nNum1Length;
            nFixOffset      = nNumOffset1;
            pStrNumToFix    = &strNum1;
        }

        string &strFixNum   = *pStrNumToFix;
        if (ALIGN_ZERO_LEFT == flag)
        {
            strFixNum.insert(nFixOffset, nFixCnt, '0');
        }
        else
        {
            strFixNum.insert(strFixNum.size(), nFixCnt, '0');
        }
    }

    //取绝对值
    static string abs(const string &num)
    {
        string strRes(num);

        FormtNumStr(strRes);
        if (IsNegative(strRes))
        {
            strRes.erase(0, 1);
        }

        return strRes;
    }

    //相等
    static bool eq(const string &strNum1, const string &strNum2)
    {
        string num1(strNum1), num2(strNum2);

        AlignNumStr(num1, num2, ALIGN_ZERO_LEFT);

        //符号不同
        if (IsNegative(num1) != IsNegative(num2)) return false;

        //相同符号
        for (size_t i = 0; i < num1.size(); ++i)
        {
            if (num1[i] != num2[i]) return false;
        }

        return true;
    }

    //大于
    static bool gt(const string &strNum1, const string &strNum2)
    {
        bool bSameSign = IsNegative(strNum1) == IsNegative(strNum2);

        if (!bSameSign)
        {
            if (IsNegative(strNum1)) return false;

            return true;
        }

        string num1(strNum1), num2(strNum2);

        AlignNumStr(num1, num2, ALIGN_ZERO_LEFT);

        for (size_t i = 0; i < num1.size(); ++i)
        {
            if (num1[i] == num2[i]) continue;

            if (num1[i] > num2[i])
            {
                return IsNegative(num1) ? false : true;
            }
            else
            {
                return IsNegative(num1) ? true : false;
            }
        }

        return false;
    }

    //大于等于
    static bool gte(const string &strNum1, const string &strNum2)
    {
        return gt(strNum1, strNum2) || eq(strNum1, strNum1);
    }

    //小于
    static bool lt(const string &strNum1, const string &strNum2)
    {
        if (eq(strNum1, strNum2)) return false;

        return !gt(strNum1, strNum2);
    }

    //小于等于
    static bool lte(const string &strNum1, const string &strNum2)
    {
        return lt(strNum1, strNum2) || eq(strNum1, strNum2);
    }

    //加
    static string Add(const string &strNum1, const string &strNum2)
    {
        string  strSum, num1(strNum1), num2(strNum2);

        AlignNumStr(num1, num2, ALIGN_ZERO_LEFT);

        if (IsNegative(num1) != IsNegative(num2))
        {
            if (IsNegative(num1))
            {
                //-10 + 5
                num1.erase(0, 1);
                return Subtract(num2, num1);
            }

            //10 + (-5)
            num2.erase(0, 1);
            return Subtract(num1, num2);
        }

        //5 + 10
        //-5 + (-10)
        size_t  nNumOffset  = num1[0] == '-' ? 1 : 0;
        int     nSum(0), nCA(0);

        strSum.resize(num1.size());
        if (nNumOffset) strSum[0] = '-';//设置负号标志
        for (size_t i = num1.size(), idx; i > nNumOffset; --i)
        {
            idx     = i - 1;
            nSum    = (num1[idx] - '0') + (num2[idx] - '0') + nCA;
            nCA     = nSum / 10;
            nSum    %= 10;

            strSum[idx] = char(nSum + '0');
        }

        if (nCA)
        {
            strSum.insert(nNumOffset, 1, char(nCA + '0'));
        }

        return strSum;
    }

    //减
    static string Subtract(const string &strNum1, const string &strNum2)
    {
        string  strResult("0"), num1(strNum1), num2(strNum2);
        string  *pLHS(NULL), *pRHS(NULL);
        char    cSign(0);

        AlignNumStr(num1, num2, ALIGN_ZERO_LEFT);

        if (eq(num1, num2)) return strResult;

        bool bSameSign = IsNegative(num1) == IsNegative(num2);

        if (!bSameSign)
        {
            if (IsNegative(num1))
            {
                //-10 - 5
                num2.insert(0, 1, '-');             
            }
            else
            {
                //10 - (-5)
                num2.erase(0, 1);
            }

            return Add(num1, num2);         
        }

        pLHS = &num1;
        pRHS = &num2;
        if (IsNegative(num1))
        {
            if (gt(num1, num2))
            {
                //-5 - (-10)
                pLHS = &num2;
                pRHS = &num1;
            }
            else
            {
                //-10 - (-5)
                cSign = '-';
            }

            //去除负号标志
            num1.erase(0, 1);
            num2.erase(0, 1);
        }
        else
        {
            //10 - 5
            if (gt(num1, num2))
            {
                ;
            }
            else
            {
                //5 - 10
                pLHS = &num2;
                pRHS = &num1;
                cSign = '-';
            }
        }

        string &strLHS = *pLHS;
        string &strRHS = *pRHS;

        strResult.resize(strLHS.size());
        for (size_t i = strLHS.size(), idx; i > 0; --i)
        {
            idx = i - 1;
            if (strLHS[idx] >= strRHS[idx])
            {
                strLHS[idx] = strLHS[idx] - strRHS[idx] + '0';
                continue;
            }

            strLHS[idx] = 10 + (strLHS[idx] - strRHS[idx]) + '0';
            for (size_t j = idx; j > 0; --j)
            {
                if (strLHS[j - 1] != '0')
                {
                    --strLHS[j - 1];
                    break;
                }

                strLHS[j - 1] = '9';
            }
        }

        if (cSign)
        {
            strLHS.insert(0, 1, cSign);
        }

        strResult = strLHS;
        return strResult;
    }

    //乘
    static string Multiply(const string &strNum1, const string &strNum2)
    {
        string strResult("0"), num1(strNum1), num2(strNum2);

        FormtNumStr(num1);
        FormtNumStr(num2);

        if (IsZero(num1) || IsZero(num2)) return strResult;

        if (eq(num1, "-1"))
        {
            if (IsNegative(num2))
            {
                num2.erase(0, 1);
            }
            else
            {
                num2.insert(0, 1, '-');
            }

            return num2;
        }

        if (eq(num2, "-1"))
        {
            if (IsNegative(num1))
            {
                num1.erase(0, 1);
            }
            else
            {
                num1.insert(0, 1, '-');
            }

            return num1;
        }

        bool    bSameSign = IsNegative(num1) == IsNegative(num2);       
        char    cSign = bSameSign ? 0 : '-';        
        string  *pLHS(NULL), *pRHS(NULL);

        if (IsNegative(num1)) num1.erase(0, 1);
        if (IsNegative(num2)) num2.erase(0, 1);

        pLHS = &num1;
        pRHS = &num2;

        //多位数作为被乘数
        if (num1.size() < num2.size())
        {
            pLHS = &num2;
            pRHS = &num1;
        }

        string  &strLHS = *pLHS;
        string  &strRHS = *pRHS;
        string  strTmp;
        int     n1, n2;
        int     nMul(0);
        int     nCA(0);

        strResult.clear();
        for (size_t i = strRHS.size(), idx = 0; i > 0; --i, ++idx)
        {
            n1 = strRHS[i - 1] - '0';
            strTmp.clear();
            strTmp.resize(strLHS.size());
            for (size_t j = strLHS.size(); j > 0; --j)
            {
                n2      = strLHS[j - 1] - '0';
                nMul    = n1 * n2 + nCA;
                nCA     = nMul / 10;
                nMul    %= 10;

                strTmp[j - 1] = nMul + '0';             
            }

            if (nCA)
            {
                strTmp.insert(0, 1, char(nCA + '0'));
            }

            //x10^n
            strTmp.insert(strTmp.size(), idx, '0');
            strResult = Add(strResult, strTmp);
        }

        if (cSign)
        {
            strResult.insert(0, 1, cSign);
        }

        return strResult;
    }

    //乘
    static string Multiply(const string &strNum1, int n)
    {
        string strNum2;
        Num2Str(n, strNum2);

        return Multiply(strNum1, strNum2);
    }

    //除
    static string Divide(const string &strNum1, const string &strNum2, string &numRemainder)
    {
        string strResult("0"), num1(strNum1), num2(strNum2), strMul, strSub;
        numRemainder = "0";

        FormtNumStr(num1);
        FormtNumStr(num2);

        if (IsZero(strNum2)) return strResult;

        bool bSameSign = IsNegative(num1) == IsNegative(num2);
        char cSign = bSameSign ? 0 : '-';

        if (lt(abs(num1), abs(num2)))
        {
            numRemainder = num1;
            return strResult;
        }

        if (eq(abs(num1), abs(num2)))
        {
            strResult = "1";
            if (cSign) strResult.insert(0, 1, cSign);
            return strResult;
        }

        if (IsNegative(num1)) num1.erase(0, 1);
        if (IsNegative(num2)) num2.erase(0, 1);

        //商位数 
        size_t num1Length   = num1.size();
        size_t num2Length   = num2.size();
        size_t nLoopCnt     = num1Length - num2Length + 1;

        strResult.resize(nLoopCnt);
        numRemainder = num1.substr(0, num2.size());
        for (size_t i = 0; i < nLoopCnt; ++i)
        {
            if (gte(numRemainder, num2))
            {
                int n = (numRemainder[0] - '0')/(num2[0] - '0' + 1);
                while (1)
                {
                    strMul = Multiply(num2, n);
                    strSub = Subtract(numRemainder, strMul);

                    if (lt(strSub, num2))
                    {
                        break;
                    }

                    ++n;
                }
                strResult[i] = char(n + '0');
                numRemainder = strSub;
            }
            else
            {
                strResult[i] = '0';
            }

            numRemainder += num1[num2Length + i];
            FormtNumStr(numRemainder);
        }

        if (cSign) strResult.insert(0, 1, cSign);
        return strResult;
    }

private:
    string m_strNum;
};

CNumber operator+(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet += rhs;
    return numRet;
}

CNumber operator-(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet -= rhs;
    return numRet;
}

CNumber operator*(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet *= rhs;
    return numRet;
}

CNumber operator/(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet /= rhs;
    return numRet;
}

CNumber operator%(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet %= rhs;
    return numRet;
}

void calc1(const CNumber &num1, const CNumber &num2, CNumber &numSum, CNumber &numSub, CNumber &numMul, CNumber &numDiv)
{
    numSum = num1 + num2;
    numSub = num1 - num2;
    numMul = num1 * num2;
    numDiv = num1 / num2;
}

int main()
{
    CNumber num1, num2, numSum, numSub, numMul, numDiv;

    if (0) {
        ASSERT(CNumber::lt("-99", "-90"));
        ASSERT(CNumber::lte("-99", "-99"));
        ASSERT(CNumber::lte("-99", "-100") == false);
        ASSERT(CNumber::lt("-99", "-100") == false);
        ASSERT(CNumber::lt("-9", "10"));
        ASSERT(CNumber::lt("5", "10"));
        ASSERT(CNumber::lte("10", "10"));
    }

    if (0) {
        num1 = "99";
        num2 = "-100";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "-1");
        ASSERT(numSub == "199");
        ASSERT(numMul == "-9900");
        ASSERT(numDiv == "0");
    }

    if (1) {
        string strRemainder, sTmp;
        int n = 19 % 8;
        CNumber::Divide("19", "8", strRemainder);
        CNumber::Num2Str(n, sTmp);
        ASSERT(sTmp == "3");
    }


    if (0) {
        calc1(num2, num1, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "-1");
        ASSERT(numSub == "-199");
    }

    if (0) {
        num1 = "-99";
        num2 = "10";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "-89");
        ASSERT(numSub == "-109");
        ASSERT(numMul == "-990");
        ASSERT(numDiv == "-9");
    }

    if (0) {
        num1 = "100";
        num2 = "100";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "200");
        ASSERT(numSub == "0");
        ASSERT(numMul == "10000");
        ASSERT(numDiv == "1");
    }

    if (0) {
        num1 = "-100";
        num2 = "100";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "0");
        ASSERT(numSub == "-200");
        ASSERT(numMul == "-10000");
        ASSERT(numDiv == "-1");
    }

    if (1) {
        num1 = "55";
        num2 = "100";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "155");
        ASSERT(numSub == "-45");
        ASSERT(numMul == "5500");
        ASSERT(numDiv == "0");
    }

    return 0;
}

vector版本

#include <stdio.h>
#include <string>
#include <vector>

#define ASSERT(b) \
    printf("%s : %s\n", #b, b ? "OK" : "Fail");

using namespace std;

class CNumber
{
    typedef vector<char> vecNum;
    enum AlignZeroFlag
    {
        ALIGN_ZERO_LEFT, //对齐时左侧填充0
        ALIGN_ZERO_RIGHT //对齐时右侧填充0
    };

public:
    //数字字符顺序 123456 => CNumber m_vNum[0] = 1

    CNumber() : m_bNegatave(false)
    {
        m_vNum.push_back(0);
    }

    CNumber(const char *num)
    {
        SetNum(num);
    }

    CNumber(const int num)
    {
        SetNum(num);
    }

    CNumber(const CNumber &other)
    {
        m_bNegatave = other.m_bNegatave;
        m_vNum      = other.m_vNum;
    }

    CNumber& operator=(const CNumber &rhs)
    {
        if (this != &rhs)
        {
            m_bNegatave = rhs.m_bNegatave;
            m_vNum      = rhs.m_vNum;
        }

        return *this;
    }

    bool IsNegative() const
    {
        return m_bNegatave;
    }

    bool IsZero() const
    {
        return m_vNum[0] == 0;
    }

    //abs(CNumber)
    CNumber abs(const CNumber &other)
    {
        CNumber num(other);

        if (num.IsNegative()) num.m_bNegatave = false;

        return num;
    }

    //++CNumber
    CNumber& operator++()
    {
        return operator+=(1);
    }

    //CNumber++
    CNumber operator++(const int)
    {
        CNumber numRet = *this;

        operator+=(1);

        return numRet;
    }

    //--CNumber
    CNumber& operator--()
    {
        return operator-=(1);
    }

    //CNumber--
    CNumber operator--(const int)
    {
        CNumber numRet = *this;

        operator-=(1);

        return numRet;
    }

    //CNumber > CNumber
    bool operator>(const CNumber &rhs) const
    {
        if (IsZero() && rhs.IsZero()) return false;

        if (IsNegative() != rhs.IsNegative())
        {
            //不同符号
            if (IsNegative()) return false;

            return true;
        }

        //相同符号

        if (m_vNum.size() != rhs.m_vNum.size())
        {
            //不同长度
            if (m_vNum.size() > rhs.m_vNum.size())
            {
                return IsNegative() ? false : true;
            }

            return IsNegative() ? true : false;
        }

        for (size_t i = 0; i < m_vNum.size(); ++i)
        {
            if (m_vNum[i] == rhs.m_vNum[i]) continue;

            if (m_vNum[i] > rhs.m_vNum[i])
            {
                //-9 < -8 || 9 > 8
                return IsNegative() ? false : true;
            }

            //-8 > -9 || 8 < 9
            return IsNegative() ? true : false;
        }

        return false;
    }

    //CNumber >= CNumber
    bool operator>=(const CNumber &rhs) const
    {
        return operator>(rhs) || operator==(rhs);
    }

    //CNumber < CNumber
    bool operator<(const CNumber &rhs) const
    {
        if (operator==(rhs)) return false;

        return !(operator>(rhs));
    }

    //CNumber <= CNumber
    bool operator<=(const CNumber &rhs) const
    {
        return operator<(rhs) || operator==(rhs);
    }

    //CNumber == CNumber
    bool operator==(const CNumber &rhs) const
    {       
        if (IsNegative() != rhs.IsNegative()) return false;

        return eq(m_vNum, rhs.m_vNum);
    }

    //CNumber + CNumber
    friend CNumber operator+(const CNumber &lhs, const CNumber &rhs);

    //CNumber += CNumber;
    CNumber& operator+=(const CNumber &rhs)
    {
        bool    bSameSign = IsNegative() == rhs.IsNegative();
        CNumber numRHS(rhs);

        if (!bSameSign)
        {
            //不同符号
            if (IsNegative())
            {
                //-m + n
                m_bNegatave = false;
                numRHS.operator -= (*this);

                *this = numRHS;
            }
            else
            {
                //m + -n
                numRHS.m_bNegatave = false;
                operator -=(numRHS);
            }

            return *this;
        }

        //相同符号

        int     nCA(0), nSum(0);

        AlignNum(m_vNum, numRHS.m_vNum, ALIGN_ZERO_LEFT);

        for (size_t i = m_vNum.size(), idx; i > 0; --i)
        {
            idx     = i - 1;
            nSum    = nCA + m_vNum[idx] + numRHS.m_vNum[idx];
            nCA     = nSum / 10;
            nSum    %= 10;

            m_vNum[idx] = nSum;
        }

        if (nCA) m_vNum.insert(m_vNum.begin(), 1, (char)nCA);

        return *this;
    }

    //CNumber - CNumber
    friend CNumber operator-(const CNumber &lhs, const CNumber &rhs);

    //CNumber -= CNumber;
    CNumber& operator-=(const CNumber &rhs)
    {
        if (*this == rhs)
        {
            SetNum((int)0);
            return *this;
        }

        bool    bSameSign = IsNegative() == rhs.IsNegative();
        CNumber numRHS(rhs);

        if (!bSameSign)
        {
            if (IsNegative())
            {
                //-m - n
                numRHS.m_bNegatave = true;
                operator += (numRHS);
            }
            else
            {
                //m - (-n)
                numRHS.m_bNegatave = false;
                operator += (numRHS);
            }

            return *this;
        }

        AlignNum(m_vNum, numRHS.m_vNum, ALIGN_ZERO_LEFT);

        int n1, n2, nSub;
        m_bNegatave = *this < numRHS;

        if (m_bNegatave)
        {
            m_vNum.swap(numRHS.m_vNum);
        }

        for (size_t i = m_vNum.size(), idx; i > 0; --i)
        {
            idx = i - 1;
            n1  = m_vNum[idx];
            n2  = numRHS.m_vNum[idx];
            nSub= n1 - n2;

            if (nSub < 0)
            {
                nSub += 10;//转换为正数

                for (size_t j = idx; j > 0; --j)
                {
                    if (m_vNum[j - 1] != 0)
                    {
                        --m_vNum[j - 1];
                        break;
                    }

                    m_vNum[j - 1] = 9;
                }
            }

            m_vNum[idx] = (char)nSub;
        }

        FormatNum(m_vNum);

        return *this;
    }

    //CNumber * CNumber
    friend CNumber operator*(const CNumber &lhs, const CNumber &rhs);

    //CNumber *= CNumber;
    CNumber& operator*=(const CNumber &rhs)
    {
        if (IsZero() || rhs.IsZero())
        {
            SetNum((int)0);
            return *this;
        }

        bool    bSameSign = IsNegative() == rhs.IsNegative();
        CNumber numRHS(rhs), numMul, numTemp;
        int     n1, n2, nMul, nCA(0);

        m_bNegatave = !bSameSign;//设置符号

        if (m_vNum.size() < numRHS.m_vNum.size())
        {
            m_vNum.swap(numRHS.m_vNum);
        }

        numMul.SetNum((int)0);
        for (size_t i = numRHS.m_vNum.size(), nMul10(0); i > 0; --i, ++nMul10)
        {
            n1 = numRHS.m_vNum[i-1];

            numTemp.SetNum((int)0);
            numTemp.m_vNum.resize(m_vNum.size());
            for (size_t j = m_vNum.size(); j > 0; --j)
            {
                n2      = m_vNum[j - 1];
                nMul    = n1 * n2 + nCA;
                nCA     = nMul / 10;
                nMul    %= 10;

                numTemp.m_vNum[j - 1] = (char)nMul;
            }
            if (nCA) numTemp.m_vNum.insert(numTemp.m_vNum.begin(), 1, (char)nCA);

            if (nMul10)
            {
                //x 10^n
                numTemp.m_vNum.insert(numTemp.m_vNum.end(), nMul10, 0);
            }

            numMul += numTemp;
        }

        m_vNum.swap(numMul.m_vNum);
        return *this;
    }

    //CNumber / CNumber
    friend CNumber operator/(const CNumber &lhs, const CNumber &rhs);

    //CNumber /= CNumber;
    CNumber& operator/=(const CNumber &rhs)
    {
        CNumber remainder;
        *this = Divide(*this, rhs, remainder);

        return *this;
    }

    //CNumber % CNumber
    friend CNumber operator%(const CNumber &lhs, const CNumber &rhs);
    //CNumber %= CNumber;
    CNumber& operator%=(const CNumber &rhs)
    {
        Divide(*this, rhs, *this); 
        return *this;
    }

    static CNumber Divide(const CNumber &lhs, const CNumber &rhs, CNumber &remainder)
    {
        CNumber numRet, numMul;
        bool    bSameSign   = lhs.IsNegative() == rhs.IsNegative();

        numRet.m_bNegatave  = !bSameSign;//设置符号

        if (eq(lhs.m_vNum, rhs.m_vNum))
        {
            remainder.SetNum((int)0);
            numRet.SetNum(1);
            numRet.m_bNegatave = !bSameSign;
            return numRet;
        }

        if (lt(lhs.m_vNum, rhs.m_vNum))
        {
            numRet.SetNum((int)0);
            remainder = lhs;
            return numRet;
        }

        size_t num1Length   = lhs.m_vNum.size();
        size_t num2Length   = rhs.m_vNum.size();
        //商位数 
        size_t nLoopCnt     = num1Length - num2Length + 1;

        numRet.m_vNum.resize(nLoopCnt);
        remainder.m_vNum.clear();
        remainder.m_vNum.resize(rhs.m_vNum.size());
        for (size_t i = 0; i < rhs.m_vNum.size(); ++i)
        {
            remainder.m_vNum[i] = lhs.m_vNum[i];
        }

        //全部设置为正数
        for (size_t i = 0; i < nLoopCnt; ++i)
        {
            if (i != 0) remainder.m_vNum.push_back(lhs.m_vNum[num2Length + i]);

            if (gte(remainder.m_vNum, rhs.m_vNum))
            {
                int n = 0;
                if (remainder.m_vNum[i] < rhs.m_vNum[i])
                {
                    //5/9
                    if (remainder.m_vNum.size() == rhs.m_vNum.size())
                    {
                        numRet.m_vNum[i] = 0;
                        continue;
                    }

                    n = (remainder.m_vNum[0]*10 + remainder.m_vNum[1]) / rhs.m_vNum[0];
                }
                else
                {
                    n = remainder.m_vNum[0] / rhs.m_vNum[0];
                }

                while (1)
                {
                    numMul = rhs * n;
                    if (lt(numMul.m_vNum ,remainder.m_vNum))
                    {
                        remainder -= numMul;
                        break;
                    }

                    --n;
                }

                numRet.m_vNum[i] = (char)n;
                FormatNum(remainder.m_vNum);
            }
            else
            {
                numRet.m_vNum[i] = 0;
            }
        }

        FormatNum(numRet.m_vNum);

        return numRet;
    }


private:
    static bool gt(const vecNum &num1, const vecNum &num2)
    {
        if (num1.size() > num2.size()) return true;

        if (num1.size() < num2.size()) return false;

        for (size_t i = 0; i < num1.size(); ++i)
        {
            if (num1[i] == num2[i]) continue;

            if (num1[i] > num2[i]) return true;
            return false;
        }

        return false;
    }

    static bool eq(const vecNum &num1, const vecNum &num2)
    {
        if (num1.size() != num2.size()) return false;

        for (size_t i = 0; i < num1.size(); ++i)
        {
            if (num1[i] != num2[i]) return false;
        }

        return true;
    }

    static bool lt(const vecNum &num1, const vecNum &num2)
    {
        if (eq(num1, num2)) return false;

        return !gt(num1, num2);
    }

    static bool gte(const vecNum &num1, const vecNum &num2)
    {
        return gt(num1, num2) || eq(num1, num2);
    }

    static void FormatNum(vecNum &num)
    {
        if (num.size() == 0)
        {
            num.push_back(0);
            return;
        }

        while (num.size() > 1)
        {
            if (num[0] != 0) break;

            num.erase(num.begin());
        }
    }

private:
    void SetNum(const char *szNum)
    {
        size_t nLen(0);

        m_bNegatave = false;
        if ((NULL == szNum) || ((nLen = strlen(szNum)) == 0))
        {

            m_vNum.push_back(0);
            return;
        }

        char c(0);
        for (size_t i = 0; i < nLen; ++i)
        {
            c = szNum[i];

            if (i == 0)
            {
                if (c == '+') continue;
                if (c == '-')
                {
                    m_bNegatave = true;
                    continue;
                }
            }

            if ((c >= '0') && (c <= '9'))
            {
                m_vNum.push_back(c - '0');
            }
        }

        if (m_vNum.empty()) m_vNum.push_back(0);
    }

    void SetNum(int num)
    {
        m_bNegatave = (num < 0);

        if (m_bNegatave) num *= -1;

        m_vNum.clear();
        while (num > 0)
        {
            m_vNum.insert(m_vNum.begin(), 1, num % 10);
            num /= 10;
        }

        if (m_vNum.empty()) m_vNum.push_back(0);
    }

    void AlignNum(vecNum &num1, vecNum &num2, AlignZeroFlag flag)
    {
        size_t  nNumLenth1  = num1.size();
        size_t  nNumLenth2  = num2.size();
        vecNum  *pAlignNum  = &num2;
        size_t  nAlignCnt   = nNumLenth1 - nNumLenth2;

        if (nNumLenth1 == nNumLenth2) return;

        if (nNumLenth1 < nNumLenth2)
        {
            pAlignNum   = &num1;
            nAlignCnt   = nNumLenth2 - nNumLenth1;
        }

        if (ALIGN_ZERO_LEFT == flag)
        {
            pAlignNum->insert(pAlignNum->begin(), nAlignCnt, 0);
        }
        else
        {
            pAlignNum->insert(pAlignNum->end(), nAlignCnt, 0);
        }
    }

private:
    bool            m_bNegatave;
    vector<char>    m_vNum;
};

CNumber operator+(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet += rhs;
    return numRet;
}

CNumber operator-(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet -= rhs;
    return numRet;
}

CNumber operator*(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet *= rhs;
    return numRet;
}

CNumber operator/(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet /= rhs;
    return numRet;
}

CNumber operator%(const CNumber &lhs, const CNumber &rhs)
{
    CNumber numRet(lhs);

    numRet %= rhs;
    return numRet;
}

void calc1(const CNumber &num1, const CNumber &num2, CNumber &numSum, CNumber &numSub, CNumber &numMul, CNumber &numDiv)
{
    numSum = num1 + num2;
    numSub = num1 - num2;
    numMul = num1 * num2;
    numDiv = num1 / num2;
}

int main()
{
    CNumber num1, num2, numSum, numSub, numMul, numDiv;

    if (1) {
        num1 = "99";
        num2 = "-100";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "-1");
        ASSERT(numSub == "199");
        ASSERT(numMul == "-9900");
        ASSERT(numDiv == "0");
    }

    if (1) {
        num1 = "-99";
        num2 = "10";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "-89");
        ASSERT(numSub == "-109");
        ASSERT(numMul == "-990");
        ASSERT(numDiv == "-9");
    }

    if (1) {
        num1 = "100";
        num2 = "100";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "200");
        ASSERT(numSub == "0");
        ASSERT(numMul == "10000");
        ASSERT(numDiv == "1");
    }

    if (1) {
        num1 = "-100";
        num2 = "100";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "0");
        ASSERT(numSub == "-200");
        ASSERT(numMul == "-10000");
        ASSERT(numDiv == "-1");
    }

    if (1) {
        num1 = "55";
        num2 = "100";
        calc1(num1, num2, numSum, numSub, numMul, numDiv);

        ASSERT(numSum == "155");
        ASSERT(numSub == "-45");
        ASSERT(numMul == "5500");
        ASSERT(numDiv == "0");
    }

    return 0;
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2018 ITdaan.com 粤ICP备14056181号