問題描述:如何實現對大數的加、減、乘、除操作。
分析問題:在處理大數時,使用long long這些基本類型就會發生溢出問題,我們可以使用c++的STL中string類型存儲這些“極限”數據。那麼就需要解決兩個string類型的相加、相減、相乘以及相除。
首先模擬兩個string類型相加:
加法處理起來不難,左操作數和右操作數從最後一位開始逐位相加,再加進位(初始進位爲0),將結果存放在臨時字符串中,該字符串大小應該爲左操作數位數加一。需要注意的是,不要忘了最後一次的進位。爲了方便處理我們讓左操作數的位數大於等於右操作數位數。
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.處理因爲減法而出現的零。
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;