1. 程式人生 > >C++實現大資料的加法、減法和乘法

C++實現大資料的加法、減法和乘法

最近在做大資料的四則運算,為了加強自己的記憶,所以就寫了這樣一篇部落格。這裡只有加法、減法和乘法的,除法的暫時未實現,以後實現了我會發上來的。

首先,什麼叫做大資料,大資料在我看來就是那些用一般的基本型別無法表示的資料(超出了範圍)。我們做這個大資料的四則運算首先得獲取到這些資料,既然一般的資料型別無法表示這些資料,那我們就用陣列來表示,因為陣列按照理論來說是可以“無限”的。為了接收方便,我們使用char型陣列來接收資料,但是在我們運算的時候,我們應該把他轉換成int型陣列,這樣便於計算和判斷陣列的進位,這個在後面會提到。

一般來說,如果資料裡面沒有小數點的話,那麼資料的運算會比較簡單,這裡我寫的程式是考慮到了小數點的問題的,所以,我們首先要處理小數點的問題。

char a[MAX],b[MAX];
int arr_1[MAX]={0},arr_2[MAX]={0};
int length_1,length_2;
int pos_1,pos_2;//記錄小數點的位置,同時代表整型資料的長度
int i = 0;
pos_1 = -1;
pos_2 = -1;
gets(a);
gets(b);
length_1 = strlen(a);
length_2 = strlen(b);
while(a[i] != '\0')
{
if (a[i] == '.')
pos_1 = i;
arr_1[i] = a[i] - '0';
i++;
}
i = 0;
while(b[i] != '\0')
{
if (b[i] == '.')
pos_2 = i;
arr_2[i] = b[i] - '0';
i++;
}

//資料沒有小數點的時候,pos等於陣列的長度
if (pos_1 < 0)
pos_1 = length_1;
if (pos_2 < 0)
pos_2 = length_2;

這裡我們接受了資料,並且把它轉換成了整型陣列,而且為了便於以後的計算 ,我們記錄了小數點的位置,當資料沒有小數點的時候我們讓pos等於資料的長度。

這裡的運算我是模擬手算來實現的,比如說加法,我們要把兩個陣列代表的位數對好,所以pos是極其重要的。

因為是模擬手算,所以我們要寫一個進位的函式來判斷那一位是否大於或等於10.

void carry(int length,int pos)
{
int temp;
for (int k = length; k >= 0; k--)
{
if (sum[k] >= 10)
{
temp = sum[k] / 10;
sum[k] = sum[k] % 10;
if (k == 0)
{
for (int i = length; i >= 0; i--)
{
sum[i+1] = sum[i];
}
sum[k] = temp;
length++;
pos++;
}
else
sum[k-1] += temp;
}
}


for (int i = 0; i < length; i++)
{
if (i == pos)
cout<<'.';
cout<<sum[i];
}
}

我使用了一個sum陣列來儲存倆個數據運算的最終結果,因為我是在資料進行運算的時候不管小數點的,所以在sum裡面是沒有小數點的,sum陣列是全域性變數,我只記住了小數點的位置,輸出到小數點位置的時候我再輸出小數點。

void numAdd(int arr_1[],int length_1,int pos_1,int arr_2[],int length_2,int pos_2)
{
int num = 0; //兩個小數點位置之間的差值,方便模擬手算
int length = 0;//sum整型長度
int length_float_1,length_float_2;//這裡代表著浮點型資料的長度
int pos;
length_float_1 = length_1 - pos_1 -1;
length_float_2 = length_2 - pos_2 -1;
/*將陣列通過小數點小標的方法來實現整型和小數位的隔離相加*/
if (pos_1 >= pos_2)
{
num = pos_1 - pos_2;
for (int i = 0; i < pos_2; i++)
arr_1[i+num] += arr_2[i];
for (length = 0; length < pos_1; length++)//將長的那一組給sum
sum[length] = arr_1[length];

else
{
num = pos_2 - pos_1;
for (int i = 0; i < pos_1; i++)
arr_2[i+num] += arr_1[i];
for (length = 0; length < pos_2; length++)
sum[length] = arr_2[length];
}
pos = length;
/*小數位的相加*/
if (length_float_1 < 0 || length_float_2 < 0)
{
if (length_float_1 < 0 && length_float_2 >= 0)
{
for (int i = 0; i < length_float_2; i++)
{
sum[pos+i] = arr_2[i+pos_2+1];
length++;
}
}
else if (length_float_2 < 0 && length_float_1 >= 0)
{
for (int i = 0; i < length_float_1; i++)
{
sum[pos+i] = arr_1[i+pos_1+1];
length++;
}
}
}
else
{
if (length_float_1 >= length_float_2)
{
for (int i = 0; i < length_float_2; i++)
arr_1[i+pos_1+1] += arr_2[i+pos_2+1];
for (int i = 0; i < length_float_1; i++)
{
sum[pos+i] = arr_1[i+pos_1+1];
length++;
}
}
else
{
for (int i = 0; i < length_float_1; i++)
arr_2[i+pos_2+1] += arr_1[i+pos_1+1];
for (int i = 0; i < length_float_2; i++)
{
sum[pos+i] = arr_2[i+pos_2+1];
length++;
}
}
}
carry(length,pos);
}

這裡加法和減法我都是分為整型部分和非整型部分,這裡pos的作用就體現出來了。通過num的值來對好陣列元素代表資料的位數,運算完成後把sum的長度和小數點的位置傳到進位函式裡面去,因為sum是全域性變數所以可以不用將它傳進去。

void subduction(int arr_1[],int length_1,int pos_1,int arr_2[],int length_2,int pos_2)
{
int num = 0;
int length = 0;
int bigFloat; //bigFloat儲存最大的浮點長度
int length_float_1,length_float_2;//這裡代表著浮點型資料的長度
int pos;
length_float_1 = length_1 - pos_1 -1;
length_float_2 = length_2 - pos_2 -1;
bigFloat = length_float_1 > length_float_2 ?length_float_1:length_float_2;
if (pos_1 >= pos_2)
{
num = pos_1 - pos_2;
for (int i =length_2-1; i >= 0; i--)
{
if (i == pos_2)
continue;
arr_1[i+num] -= arr_2[i];
if (arr_1[i+num] < 0 && (i+num) != 0)
{
arr_1[i+num] += 10;
if (i-1 == pos_2)
arr_1[i+num-2]--;
else
arr_1[i+num-1]--;
}
}
if (length_float_1 < 0)
{
if (length_float_2 < 0)
{
length = length_1;
pos = pos_1;
}
else
{
length = length_1 + length_float_2;
pos = pos_1;
}
}
else
{
pos = pos_1;
length = pos_1 + bigFloat;
}
for (int i = 0; i < length; i++)
{
if (i >= pos_1)
sum[i] = arr_1[i+1];
else
sum[i] = arr_1[i];
}
}
else
{
num = pos_2 - pos_1;
for (int i =length_1-1; i >= 0; i--)
{
if (i == pos_1)
continue;
arr_2[i+num] -= arr_1[i];
if (arr_2[i+num] < 0 && (i+num) != 0)
{
arr_2[i+num] += 10;
if (i-1 == pos_1)
arr_2[i+num-2]--;
else
arr_2[i+num-1]--;
}
}
if (length_float_2 < 0)
{
if (length_float_1 < 0)
{
length = length_2;
pos = pos_2;
}
else
{
length = length_2 + length_float_1;
pos = pos_2;
}
}
else
{
pos = pos_2;
length = pos_2 + bigFloat;
}
for (int i = 0; i < length; i++)
{
if (i >= pos_2)
sum[i] = arr_2[i+1];
else
sum[i] = arr_2[i];
}
cout<<'-';
}
carry(length,pos);
}

減法和加法類似,同樣是分為兩部分,兩個部分的較長的給sum,最後判斷進位。

void multiplication(int arr_1[],int length_1,int pos_1,int arr_2[],int length_2,int pos_2)
{
int length = 0;
int pos = 0;
int length_float_1,length_float_2;//這裡代表著浮點型資料的長度
length_float_1 = length_1 - pos_1 -1;
length_float_2 = length_2 - pos_2 -1;
/*將有小數位的數變成無小數位的*/
if (length_float_1 >= 0)
{
for (int i = 0; i < length_float_1; i++)
{
arr_1[i+pos_1] = arr_1[i+pos_1+1];
}
length_1 -= length_float_1;
}
else
length_float_1 = 0;
if (length_float_2 >= 0)
{
for (int i = 0; i < length_float_2; i++)
{
arr_2[i+pos_2] = arr_2[i+pos_2+1];
}
length_2 -= length_float_2;
}
else
length_float_2 = 0;
for (int i = 0; i < length_1; i++)
{
for (int j = 0; j < length_2; j++)
{
sum[i+j] += (arr_1[i] * arr_2[j]);
}
}
length = length_1 + length_2 - 1;
pos = length - (length_float_1 + length_float_2);
carry(length,pos);
}

乘法的話和加法就有些不同。因為乘法的手算是這個數裡面的一位數與另一個數的全部位數一個個相乘,這裡我們可以注意它的陣列的小標的變化sum[i+j] += (arr_1[i] * arr_2[j]);兩個巢狀for迴圈很好解決了下標的問題,你們可以去寫一些資料來試試,sum 的下標就會等兩個下標的相加。如果沒有小數點的話,我們直接使用兩個迴圈來做 ,直接結果就出來了,但是這裡要考慮到小數點的問題,所以我們就先對資料進行去小數點,我們只需要記錄小數點的個數,將兩個小數點的個數相加就是最後結果的小數點的個數了。

沒有寫過部落格,並且自己的功底不是很好,寫的不好的地方歡迎大家來批評。大家有什麼更好的辦法也可以告訴我,共同學習和進步。