1. 程式人生 > >從大整數乘法的實現到 Karatsuba 快速演算法

從大整數乘法的實現到 Karatsuba 快速演算法

Karatsuba 快速乘積演算法是具有獨特合併過程(combine/merge)的分治演算法(Karatsuba 是俄羅斯人)。此演算法主要是對兩個整數進行相乘,並不適用於低位數(如 int 的 32 位的整數)。

1. 大整數乘法的實現

所謂的大整數,就是超出程式語言關於 integral 型別的最大值的那些位數很大的數,也即如果用這些型別進行儲存的話,會造成數值溢位(arithmetic overflow),此時可以使用 vector<int> 逐位儲存這些數。

執行兩數的乘法的方法就是我們小學學乘法時所採用的方式,normalize 負責處理每一位上的進位情況。

void normalize(vector<int>& c){
    for (int i = 0; i < c.size()-1; ++i){
        c[i+1] += c[i]/10;
        c[i] %= 10;
    }
}

vector<int> multiply(const vector<int>& a, const vector<int>& b){
    vector<int> c(a.size()+b.size(), 0);
    for (int i = 0; i < a.size(); ++i){
        for
(int j = 0; j < b.size(); ++j){ c[i+j] += a[i]*b[j]; } } normalize(c); return c; }

2. Karatsuba 快速演算法

Karatsuba 快速乘積演算法首先將兩個整數分別一分為二。例如,a 和 b 各位 256 位的整數,那麼使用 a1b1 儲存前 128 為,而 a0b0 中儲存後 128 位。分割後,ab 可寫成如下的形式。

{a=a110128+a0b=b110128+b0

所以將 a×b 分割成四項式有如下等式:

a
×b=
=
(a1×10128+a0)(b110128+b0)a1b1z210256+(a0b1+a1b0)z110128+a0b0z0

首先根據 z0=a0b0,z2=a1b1 計算 z0,z1,然後利用以下等式:

(a0+a1)(b0+b1)=z0+z1+z2
因此:
  • z2 = a1 * b1
  • z0 = a0 * b0
  • z1 = (a0 + b0)(a1 + b1)-z2-z0