从大整数乘法的实现到 Karatsuba 快速算法

时间:2022-08-06 00:15:39

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 位的整数,那么使用 a1 和 b1 保存前 128 为,而 a0 和 b0 中保存后 128 位。分割后,a 和 b 可写成如下的形式。

{a=a1⋅10128+a0b=b1⋅10128+b0

所以将 a×b 分割成四项式有如下等式:

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

首先根据 z0=a0⋅b0,z2=a1⋅b1 计算 z0,z1,然后利用以下等式:

(a0+a1)⋅(b0+b1)=z0+z1+z2

因此:

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