### 數字字符串四則運算

#### 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)
{

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);
}

}

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');
}

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;
}
``````