在資料加密處理中有很多複雜的加密演算法,這些加密演算法往往會用到很多超大的整數運算。不過,程式語言對資料的大小會有一定的限制,資料太大就會出現資料溢位的情況,這是無法進行大整型資料運算的。本文將和大家一起學習如何實現大整數的資料運算,本文**我們使用c++實現。
對於乘數運算有一種比較簡單較為容易理解的方法,我們可以利用小學時期學的列豎式的計算方法進行乘法運算。
參考上圖中的列豎式計算方法,我們進行**實現。
#include
#include
#include
#include
#include
#include
std::string multiply
(std::string a, std::string b)
}int n = a.
size()
+ b.
size()
;int sum[n]
;memset
(sum,0,
sizeof
(int
)*n)
;for
(int n =
0; n < n; n++
)
i++; j--;}
if( n+
1< n )
}bool zerostartflag =
true
;for
(int i = n-
1; i >=
0; i--
)
zerostartflag =
false
; result.
(std::
to_string
(sum[i]))
;}return result;
}int
main()
為了方便我們先將各個乘數做了翻轉處理,最後需要再將結果翻轉回來。在運算過程中用來存放乘法運算結果的陣列,我們沒有進行移位處理同列相加,而是對角線相加,這樣可以減少空間和運算步驟。上面的**執行結果如下所示。
因為字串的長度沒有特別的限制,所以上面的演算法可以適用大整數運算。
雖然上面的列豎式的方法可以很好的解決大整數乘法的問題,但是我們還用一種更加高效的方法可以選擇,這就是分治(divide and conquer)演算法。它是一種非常重要的演算法,可以應用到很多領域,比如快速排序,二分搜尋等。從演算法的名字我們可以看出它是將大的問題拆分進行細化,由大變小,先將小的問題解決,最終將這個問題解決,所以叫divide and conquer。在這裡我們可以通過這種方法將大整數進行拆分,拆分成乙個個可以通過程式語言直接進行運算的小整進行計算,最後求得到大整數的值。
假設有兩個大整數,我們設為a(大小為n位)和b(大小為m位),這裡我們將使用二分法對資料進行拆分,這兩個整數我們可以分解為:
a =a
1∗10
n/2+
a0a = a_1 * 10^ + a_0
a=a1∗
10n/
2+a0b=
b1∗1
0m/2
+b0b = b_1 * 10^ + b_0
b=b1∗
10m/
2+b0
則,
3=a1b1
z_3 = a_1b_1
z3=a1
b1
z 2=
a1b0
z_2 = a_1b_0
z2=a1
b0
z 1=
a0b1
z_1 = a_0b_1
z1=a0
b1
z 0=
a0b0
z_0 = a_0b_0
z0=a0
b0
根據上面公式裡,我們可以將a*b分解為四個小的整數的乘法,即z3,z2,z1,z0四個表示式。如果分解出來的乘法數值還是很大,還可以按照同樣的方法進行拆解直到拆解成較小的數值乘法,直到計算機程式語言可以直接運算。
比如,上面的3456和1234相乘,參考下圖通過二分法逐級對整數進行拆分,我們將兩個整數拆分到一位整數進行運算。
下面我們看一下分治演算法的**實現,這裡我們使用遞迴的方法。
#include
#include
#include
#include
#include
#include
#include
std::string add
(std::string a, std::string b)
} std::string result="";
bool zerostartflag =
true
;for
(int i = n-
1; i >=
0; i--
)
zerostartflag =
false
; result.
(std::
to_string
(sum[i]))
;}return result;
}std::string divideandconquer
(std::string a, std::string b)
int n = a.
size()
;int m = b.
size()
;int halfn = n/2;
int halfm = m/2;
std::string a0 =
"0";
std::string a1 =
"0";
if(a.
size()
> halfn && halfn >0)
else
std::string b0 =
"0";
std::string b1 =
"0";
if(b.
size()
> halfm && halfm >0)
else
std::string a1b1 =
divideandconquer
(a1, b1)
; std::string a0b0 =
divideandconquer
(a0, b0)
; std::string a1b0 =
divideandconquer
(a1, b0)
; std::string a0b1 =
divideandconquer
(a0, b1)
;
a1b1.
((n - halfn)
+(m - halfm)
,'0');
a1b0.
(n - halfn,
'0')
; a0b1.
(m - halfm,
'0')
; std::string result ="";
result =
add(a1b1, a1b0)
; result =
add(result, a0b1)
; result =
add(result, a0b0)
;return result;
}int
main()
程式的執行結果如下: 分治 大整數乘法
第一次自己完整寫對,多多指教 演算法思路 分治。第一步 經過預處理將兩個整數變為長度一樣的兩個數 短的在前面補0 第二部 把兩個大整數都平分為前後兩部分 第三部 按以下公式計算 實現大數乘法之前實現了大數加減法 公式 x a 10 n 2 b y c 10 n 2 d xy ac 10 n a b ...
分治 大整數乘法
問題描述 設x和y是兩個n位的二進位制整數,現在要計算它們的乘積xy,傳統方法計算每2個1位數乘法或加法都看作一步運算,這樣需要o n2 次位運算,代價太高,現在運用分治法設計乙個更有效的大整數乘法演算法。當n 1時,計算x y就是一次位乘。現在對x y進行劃分,把x和y各分為兩段,每段長為n 2 ...
分治演算法 大整數乘法
用分治演算法程式設計實現兩個n 位十進位製大整數的乘法運算。分析 用分治演算法程式設計實現兩個n 位十進位製大整數的乘法運算。演算法描述 兩個十進位制的數 x y x a 10 n1 b y c 10 n2 d 則 x y a 10 n1 b c 10 n2 d 設乙個陣列,將其看做10000 進製...