大數運算 加法(C C 實現)

2021-09-12 02:07:24 字數 4424 閱讀 5398

**:

前言在很多情況下,c/c++所提供的基本資料型別已經不能滿足我們的需求了,所以我們需要一種方法來解決一些大數的運算,在小學進行加法運算的時候,無論資料是什麼,有多少位,都通通採取列豎式的方法進行計算並得出結果,本文將使用陣列模擬列豎式計算來解決大數的加法運算。

問題分析

首先我們先給定一組資料,來輔助說明整個計算過程

a = 987654321

b = 56789

計算 a + b 的結果

將兩個數字的每一位分別存入兩個陣列:因為所給定的資料不是很大,這裡就開闢長度為10的陣列進行說明,a陣列(a)用來儲存數字a的每一位,b陣列(b)用來儲存數字b的每一位,c陣列(c)用來儲存計算的結果(在程式中開闢乙個新的陣列,陣列的每一位都是隨機數,所以需要將陣列初始化,把陣列的每一位都賦值為0)。陣列0

1234

5678

9a98

7654

3210

b567

8900

000c

0000

0000

00我們通過某種方式將其存入了陣列中,從左往右觀察上面這個**,雖然我們想計算的是987654321 + 56789,但是存入陣列中後我們發現,現在已經無法分辨 a 和 b 的值了。

a 的值變成了9876543210?

b 的值變成了5678900000?

我們可以記錄下數字 a 最後一位所在陣列的位置,數字 b 最後一位所在陣列的位置,這樣雖然不會出現上面的問題了,但是在實際的計算過程中會很繁瑣,並伴隨著各種問題。接下來,我們換一種思路來將數字存入陣列(逆序存入),存入的結果如下表所示:陣列0

1234

5678

9a12

3456

7890

b887

6500

000c

0000

0000

00此時我們從右往左看這個表:

a = 0987654321 = 987654321

b = 0000056789 = 56789

這樣的結果才是我們所需要的,接下來我們繼續來模仿列豎式的方法進行計算,c[n] = a[n] + b[n] + c[n], 如果結果大於等於10,我們就向前進一位。

c[0] = a[0] + b[0] + c[0] = 1 + 9 + 0 = 10,結果等於10, 向前進一位,進製之後c[1] = 1,c[0] = 0;

c[1] = a[1] + b[1] + c[1] = 2 + 8 + 1 = 11,結果大於10,向前進一位,進製之後c[2] = 1, c[1] = 1;

c[2] = a[2] + b[2] + c[2] = 3 + 7 + 1 = 11,結果大於10,向前進一位,進製之後c[3] = 1, c[2] = 1;

重複這樣的操作,直到陣列的最後乙個元素。

執行完上述操作後,**變成如下所示:陣列0

1234

5678

9a12

3456

7890

b987

6500

000c

0111

1778

90現在我們從右向左觀察陣列c(c),每一位分別是0987711110,如果忽略前置0,結果就是98771110,這便是987654321 + 56789的結果。

以上就是大數加法的基本步驟了,實際上,我們並不需要陣列 c 進行輔助運算,前文中使用原因只是為了方便說明,如果不利用c陣列,那麼初始的表將會變成如下樣子:陣列0

1234

5678

9a12

3456

7890

b987

6500

000只需要將陣列a中的每乙個元素加到陣列b中,即b[n] = a[n] + b[n],再根據結果決定是否需要進製。

b[0] = a[0] + b[0] = 1 + 9 = 10,結果等於10,向前進一位,進製之後b[1] = 9, b[0] = 0;

b[1] = a[1] + b[1] = 2 + 9 = 11,結果大於10,向前進一位,進製之後b[2] = 8, b[1] = 1;

b[2] = a[2] + b[2] = 3 + 8 = 11,結果大於10,向前進一位,進製之後b[3] = 7, b[2] = 1;

重複這樣的操作,直到陣列的最後乙個元素。

執行完上述操作後,我們可以得到這樣乙個表:陣列0

1234

5678

9a12

3456

7890

b011

1177

890結果同樣是987711110

**實現

首先是如何逆序將資料存入陣列,我們可以在輸入資料的時候將 a 和 b 分別存入兩個字串,然後獲取字串的長度,從字串的最後乙個元素開始依次新增到陣列中,新增的時候只需要把字元減去字元0。

//這裡str1是字串,a是陣列

//逆序存入str1中的元素到a陣列

for(

int i =

strlen

(str1)-1

, j =

0; i >=

0; i--

) a[j++

]= str1[i]

-'0'

;//這裡str2是字串,b是陣列

//逆序存入str2中的元素到b陣列

for(

int i =

strlen

(str2)-1

, j =

0; i >=

0; i--

) b[j++

]= str2[i]

-'0'

;//執行完這兩個迴圈之後就完成了逆序存入的操作

2.相加和進製:兩個陣列的每一位都分別相加,再通過相加的結果判斷是否需要進製,maxn為陣列的長度,但是這樣的話,會有很多沒用意義的計算,就比如上文中的例子,a[9] + b[9]就是沒有意義的,後面會說到這個該如何優化。

//這裡的maxn是陣列的長度

for(

int i =

0; i < maxn; i++

)}

3.結果的輸出:因為輸出的時候需要從陣列的最後一位向前輸出,也就是說會有很多前置的零,上文中的例子,如果直接輸出的話結果就是0987711110,但是我們並不需要前置0,所以在輸出結果的時候應該過濾掉前置0,也就是說在輸出的時候從第乙個不為0的位置開始輸出,實現這個的方式有很多,我是用以下的方式實現的輸出:

//這裡的maxn同上

int i;

//注意:這個for迴圈有乙個分號

for(i = maxn -

1; i >=

0&& b[i]==0

; i--);

if(i >=0)

for(

; i >=

0; i--

) cout << b[i]

;else

cout <<0;

cout << endl;

下面是完整的**:

#include

#include

#include

using

namespace std;

const

int maxn =

1000

;char str1[maxn]

, str2[maxn]

;int a[maxn]

, b[maxn]

;void

sum()}

//輸出結果

int i;

//過濾掉前置0

for(i = maxn -

1; i >=

0&& b[i]==0

; i--);

if(i >=0)

for(

; i >=

0; i--

) cout << b[i]

;//如果儲存結果的陣列中全部為0,上面的操作會過濾掉所有的0,不會有輸出,所以這裡輸出乙個0

else

cout <<0;

cout << endl;

}int

main()

關於maxn

maxn是在程式中定義的乙個常量,但是在計算的過程中如果直接使用,會執行很多沒有意義的計算過程,我們可以這樣做乙個優化,定義乙個變數max,令max的值等於最長的字串長度 + 1,即:

max = max(strlen(str1), strlen(str2)) + 1;

加1的原因:n位+n位的結果可能會是n+1位,舉個例子來說,如果計算999+111,實際的結果應該是1110,如果不加1,那麼輸出的結果就是110。

用max替換sum()函式中的一些邊界值即可。

大數運算 加法(C C 實現)

前言 問題分析 將兩個數字的每一位分別存入兩個陣列 因為所給定的資料不是很大,這裡就開闢長度為10的陣列進行說明,a陣列 a 用來儲存數字a的每一位,b陣列 b 用來儲存數字b的每一位,c陣列 c 用來儲存計算的結果 在程式中開闢乙個新的陣列,陣列的每一位都是隨機數,所以需要將陣列初始化,把陣列的每...

大數運算 加法

include include include void add const char a,const char b,char c if carry 0 result result length carry 0 while result length 0 c result result length...

大數運算 加法

究竟為什麼要用大數加法呢。我們來看下資料 bool型為布林型,佔1個位元組,取值0或1。bool型為int型,一般認為佔4個位元組,取值true false error。sbyte型為有符號8位整數,佔1個位元組,取值範圍在128 127之間。bytet型為無符號16位整數,佔2個位元組,取值範圍在...