今天有空研究下大數相乘,按照個人習慣在看別人的演算法之前,我還是習慣自己先研究一番。
先解釋下何為大數相乘,所以大數相乘即由於乘數和被乘數以及相乘結果超過語言級自帶的範圍時,或者有嚴格的精度要求時的計算。例如2個30多位的數字相乘。
很多人給出的大致演算法是使用程式模擬手工計算乘法,這裡主要涉及頻繁的進製,對齊。我仔細分析了下發現還是有很多技巧可以提公升的。下面是具體的分析過程:
假設:大數在2個陣列中儲存,而且順序是一致的,即高位在前。
陣列1:char a[ ],陣列2:cahr b[ ],
m=strlen(a),n=strlen(b)
最初的想法是:
sumfor(i = m-1; i >= 0; i--)
for(j = n-1 ; j >= 0; j--)
sum = a[i] * b[j] * 10^(i+j) + sum // a*b* 進製
問題1:沒有這樣的資料型別 sum,能夠存放足夠大的數字
解決方法: 忽略進製,把每一位看成乙個字元,只要保證其所在位置正確即可。
我們以乙個二位陣列記錄臨時結果,至於進製計算的過程可以不考慮,在最後統一進製。這一點其實很好理解,
例如2點60分,雖然不屬於常規的表達方式,但是在邏輯上同3點是一樣的,同樣 101,可以表達為:9*10+11*1 。
這個二維陣列橫座標是 數字,縱座標是 每一位的數值。
由此引申出另外2個變數:
相乘後結果的位數最大值:m+n = x
關於每一位的最大值,由於每一位相乘最大值不超過100,而最多出現的次數是 max(m,n) = y,那麼這個數最大值為:100 * y
/* int 二維陣列,不太合適,這部分內容可以忽略
因此這個陣列定義為:unsigned t[ x ][ m ( 100 * y)] 備註: m:需要int的最小位數 n
由於1個int(32位)能存放的最大整數為:4.294967295×10⁹ 已經很大了,我們可以簡化處理下:
#define max_vertical 1,於是二維陣列被定義為:unsigned t[x][max_vertical] */
/* 再次否定 不方便運算
這個陣列定義為: char t[ x ][ log(2, 100*y)]
簡化下:#define max_vertical 30,於是二維陣列被定義為:unsigned t[x][
max_vertical
] */
由於1個int(32位)能存放的最大整數為:4.294967295×10⁹ 已經很大了,我們使用1個int 型一維陣列就足夠了,
而且方便計算。
我們再分析下,每2個數字相乘對應到陣列的第幾個位置,可以簡單歸納下不難得出: i + j 就對應的列上。
因此,我們進一步優化**為:
//初始化 t
for(i = m-1; i >= 0; i--)
for(j = n-1 ; j >= 0; j--)
t[ i+j ] =
t[ i+j ] + a[ i ] * b[ j ] ;
迴圈結束,我們得到乙個非常規表達的結果,即1個3位數為 1*100+ 21*10+33*1,接下來就是最這個結果進行常規化。
我們可以從低位開始對每位對10求餘,餘數即當前位的值;求商,商即要進製的值;
我們按照相反順序把結果列印出來或者儲存到字元中即是我們想要的結果。
下面是完整的**(已經編譯並測試通過):
#include int huge_num_plus(const char *a, const char *b, char *output)
/* for test
printf("mid_rec:\n");
for(i=0; i
大數相乘 大數相加
大數相乘 大數相乘 1 include includeint main int ans i while lb 0 int cnt j for i 0 i 0 i if e i break 去除前面多餘的0 if i 1 else 當結果是0的時候 printf 0 printf n return 0...
大數相乘演算法
啥也說,直接給 高精度的乘法,乘數的位數沒有限制,小數點後面的位數也沒有限制 輸入引數 乘數 str1,str2 輸出引數 str str1 str2 返回值型別 string string large mult string str1,string str2,string str 輸出引數 ass...
c 大數相乘
using system using system.collections.generic using system.text namespace numbers if ch1.length 0 return true return true public static string getmuti...