1. 程式人生 > 實用技巧 >兩個超級大整數的相加,相乘

兩個超級大整數的相加,相乘

我們很容易理解兩個超級大的整數的相加或者相乘不能用int,long, long long 來承載,因為還是很可能溢位。

我們c,c++語言起步的,很容易想到用char陣列或者string來無限承載超大數。我開始也這麼想的。後面突然想到vector<int>也可以承載。其實沒有差別。

很多同學寫不出兩個超大數的乘法,這裡提供一個解法:

(1)核心是資料規範化,比如有個數串: [低位] 30,45,21,100[高位] 我們需要轉成: 0,8,5,2,0,1 即把進位體現在他的高位中(對於30,需要留下0然後把3進位到高位去.所以45會編出45+3=48. 對於48,需要留下8,把4進位到高位去,所以21+4=25. 。。。。。。. 對於最後一個100,需要加2: 100+2=102,然後留下2,把10進位到高位:0+10=10(高位初始化為0)。 留下0,把1進位到高位: 0+1=1 . 1<9所以無需再進位計算了)。

(2) 我們還需要寫一個兩個大數相加,因為我們很容易知道45*32可以轉出45*2 + 45*30 。 所以可以把45*2作為一個大數,45*30作為一個大數,求這兩個大數的和。所以需要寫兩個大數相加的函式。

(3)最後我們寫一個兩個大數的乘法,然後把各層乘法當作一個大數進行加操作。比如45*32,我們吧45*2的結果作為一個大數, 45*30的結果作為一個大數。然後進行上面的大數相加計算。

具體例子如下:

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include
<stdio.h> #include<stdlib.h> #include<unistd.h> #include<math.h> using namespace std; void showV(const vector<int>& obj) //列印 { for(int i = 0; i < obj.size(); ++i) { cout << obj[i] << "/"; } } ///////////////////////單個一串數字變換成正常的數值的函式///////////////////////////////////// //103,35,23,15--變換成整數值--->106745 (大數在左,小數在右)
const vector<int> getNum(const vector<int>& obj) { vector<int> newNum(obj); reverse(newNum.begin(), newNum.end()); //把數值整體翻轉,這樣就可以下標0對應最低位,算進位制的時候從下標0開始向下標size-1開始算起 for(int i = 0; i < newNum.size(); ++i) { if (newNum[i] > 9) //如果當前下標對應的資料>= 10,則 value/10表示進位制,value%10表示剔除進位制後的真正資料 { newNum[i+1] += newNum[i]/10; //i+1的位置自加來自低位的進位制 newNum[i] = newNum[i]%10; } //當把倒數第二個算完後,倒數第二個的進位制已經在最後一個上體現了。如果最後一個的數值>=10,那麼則需要在最後一個後面再新增一個位置進行進位制的進位 if (i == newNum.size() - 2) { if( newNum[newNum.size()-1] >= 10 ) { newNum.push_back(0); } } } reverse(newNum.begin(), newNum.end()); //上面為了計算方便所以資料整體翻轉了,這裡再翻轉回來。 return newNum; } void test_getNum() { vector<int> tmp; tmp.push_back(103); tmp.push_back(35); tmp.push_back(23); tmp.push_back(15); vector<int> digital = getNum(tmp); showV(digital); cout<<endl; } /////////////////////////////////兩個大數相加的函式///////////////////////////////////////////// const vector<int> addVec(vector<int> addLeft, vector<int> addRight) { addLeft = getNum(addLeft); addRight = getNum(addRight); vector<int> sum; reverse(addLeft.begin(), addLeft.end()); reverse(addRight.begin(), addRight.end()); if (addLeft.size() > addRight.size()) //翻轉之後就成了先低位對齊,然後從低位加到高位 { sum = addLeft; for(int i = 0; i < addRight.size(); ++i) { sum[i] += addRight[i]; } } else { sum = addRight; for(int i = 0; i < addLeft.size(); ++i) { sum[i] += addLeft[i]; } } reverse(sum.begin(), sum.end()); sum = getNum(sum); return sum; } void test_addVec() { vector<int> first; first.push_back(7); first.push_back(8); first.push_back(2); first.push_back(3); first.push_back(4); vector<int> second; second.push_back(9); second.push_back(9); second.push_back(9); second.push_back(9); second.push_back(9); second.push_back(0); showV(first); cout<<endl; showV(second); cout<<endl; vector<int> sum = addVec(first, second); showV(sum); cout<<endl; } ////////////////////////////兩個大數相乘的函式////////////////////////////////////////
#if 0
/* bug 版本 : 因為兩個數都可以無限大,所以curNum確定不會越限? 所以有bug*/ const vector<int> mulVec(vector<int> mulLeft, vector<int> mulRight) { vector<int> result(1,0); reverse(mulRight.begin(), mulRight.end()); for(int i = 0; i < mulRight.size(); ++i) { vector<int> thisLoopValue(mulLeft); int curNum = mulRight[i] * (int)pow(10,i); for(int j = 0; j < thisLoopValue.size(); ++j) { thisLoopValue[j] *= curNum; } thisLoopValue = getNum(thisLoopValue); result = addVec(result, thisLoopValue); } result = getNum(result); return result; } #endif

const vector<int> mulVec(vector<int> mulLeft, vector<int> mulRight)
{
vector<int> result(1,0);


reverse(mulRight.begin(), mulRight.end());
for(int i = 0; i < mulRight.size(); ++i)
{
vector<int> thisLoopValue(mulLeft);


//long long curNum = mulRight[i] * (long long)pow(10,i);
long long curNum = mulRight[i];


for(int j = 0; j < thisLoopValue.size(); ++j)
{
      thisLoopValue[j] *= curNum;
    }
    for(int k = 0; k < i; k++)//往最末尾補0. 比如計算25*21時候 算25*20 可以算25*2,在得出的結果最小數那裡塞進一個0進去,來等價25*20
    {
      thisLoopValue.push_back(0);
    }


    thisLoopValue = getNum(thisLoopValue);
    result = addVec(result, thisLoopValue);
    result = getNum(result);
}

return result;
}


void test_mulVec() { vector<int> first; first.push_back(8); first.push_back(8); first.push_back(9); first.push_back(0); first.push_back(2); first.push_back(9); first.push_back(8); first.push_back(8); first.push_back(1); vector<int> second; second.push_back(8); second.push_back(9); second.push_back(8); showV(first); cout<<endl; showV(second); cout<<endl; vector<int> mulResult = mulVec(first, second); showV(mulResult); cout<<endl; } ///////////////////////////////////////////// int main() { //test_getNum(); //test_addVec(); test_mulVec(); };


[mayc@ /data_disk2/Share/ftproot/myc]$./testme
8/8/9/0/2/9/8/8/1/
8/9/8/
7/9/8/3/4/8/8/3/3/1/3/8/

即: 889029881 * 898 = 798348833138
8/8/9/0/2/9/8/8/1/ * 8/8/9/0/2/9/8/8/1/ = 7/9/0/3/7/4/1/2/9/3/1/0/8/7/4/1/6/1/