大數四則運算

問題描述:如何實現對大數的加、減、乘、除操作。

分析問題:在處理大數時,使用long long這些基本類型就會發生溢出問題,我們可以使用c++STLstring類型存儲這些“極限”數據。那麼就需要解決兩個string類型的相加、相減、相乘以及相除。

首先模擬兩個string類型相加:

  加法處理起來不難,左操作數和右操作數從最後一位開始逐位相加,再加進位(初始進位爲0),將結果存放在臨時字符串中,該字符串大小應該爲左操作數位數加一。需要注意的是,不要忘了最後一次的進位。爲了方便處理我們讓左操作數的位數大於等於右操作數位數。

wKiom1byhMLzNWAaAAAs0W_w_o4416.png

char cStep = 0;
string retStr;
retStr.resize(iLSize + 1);
    //逐位相加再加進位
for (int iIdx = 1; iIdx < iLSize; ++iIdx)
{
    char cRet = left[iLSize - iIdx] - '0' + cStep;
    if (iIdx < iRSize)            
    {
         cRet += (right[iRSize - iIdx] - '0');
    }
    retStr[iLSize - iIdx + 1] = (cRet % 10) + '0';
    cStep = cRet / 10;
}
retStr[1] = cStep + '0';

減法也是逐位相減,若結果小於零需要借位,將左操作數前一位減1,相減的結果加10保存在結果字符串對應位。這裏我們讓左操作數大於等於右操作數,若本身左操作數小於右操作數,則交換他們並將符號位賦爲‘-’。

string retStr;
retStr.resize(iLSize);
retStr[0] = cSymbol;
//逐位相減
//1.取左操作數  2.取右操作數(未超出)  3.相減<0,借位:左前一位-=1,結果+10保存
for (int iIdx = 1; iIdx < iLSize; ++iIdx)
{
    char cRet = left[iLSize - iIdx] - '0';
    if (iIdx < iRSize)
    {
        cRet -= right[iRSize - iIdx] - '0';
    }
    if (cRet < 0)
    {
        left[iLSize - iIdx - 1] -= 1;
        cRet += 10;
    }
    retStr[iLSize - iIdx] = cRet + '0';
}


大數乘法需要取操作數1的每一位去和操作數2的每一位相乘,然後錯位相加。每一次內循環完成之後,下一次的結果存放需要往前錯一位。結果字符串的長度應該是兩個操作數之和減一。(讓長度小的作左操作數)

for (int iIdx = 1; iIdx < iLSize; ++iIdx)
{
    char cLeft = left[iLSize - iIdx] - '0';
    char cStep = 0;
    if (0 == cLeft)    //遇0直接錯位
    {
        iOffSet++;
        continue;
    }
    for (int iRIdx = 1; iRIdx < iRSize; ++iRIdx)
    {
        char cRet = cLeft*(right[iRSize - iRIdx] - '0');
        cRet += cStep;
        cRet += (retStr[iDataLen - iOffSet - iRIdx] - '0');//加上對應位置原有的值
        retStr[iDataLen - iOffSet - iRIdx] = cRet % 10 + '0';     
        cStep = cRet / 10;
    }
    retStr[iDataLen - iOffSet - iRSize] += cStep;
    iOffSet++;
}


除法:1.取被除數大於除數的區間字符串;2.區間字符串和除數循環相減,直到區間字符串小於除數;3.處理因爲減法而出現的零。

wKiom1byg6qQ_HOdAAAqkGdWAxU253.png

for (int iIdx = 0; iIdx < iLSize - 1; ++iIdx)
{
    //處理被除數中的‘0’
    if ('0' == *pLeft)
    {
        pLeft++;
        retStr.append(1, '0');
        iIdx++;
        continue;
    }
    if  (!IsLeftStrBig(pLeft, iLSize, pRight, iRSize - 1))//用DataLen確定區間字符串
    {
        Datalen++;
        if (iIdx + Datalen > iLSize)
        {
            break;
        }
        retStr.append(1, '0');
        continue;
    }
    else
    {
        retStr.append(1, subLoop(pLeft, Datalen, pRight, iRSize - 1)); //循環相減
    }
    //刪除掉因爲進行減法而出現的0
    while ('0' == *pLeft && Datalen > 0)
    {
        pLeft++;
        iIdx++;
        Datalen--;
    }
    Datalen++;
    if (iIdx + Datalen > iLSize)
    {
    break;
    }
}
return retStr;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章