看了就會的大整數乘法運算與分治演算法

2021-10-10 13:24:15 字數 4026 閱讀 4146

在資料加密處理中有很多複雜的加密演算法,這些加密演算法往往會用到很多超大的整數運算。不過,程式語言對資料的大小會有一定的限制,資料太大就會出現資料溢位的情況,這是無法進行大整型資料運算的。本文將和大家一起學習如何實現大整數的資料運算,本文**我們使用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+a0​b=

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 進製...