在计算机科学中,乘法是最基础的算术运算之一,但大数乘法的效率问题却一直是算法研究的核心课题。从小学课堂上的竖式乘法,到高斯的复数乘法优化,再到能突破时间壁垒的Karatsuba 算法,每一次创新都让大数乘法的效率实现质的提升。本文将结合经典的算法理论,从时间复杂度的角度,梳理大数乘法的算法演进过程,带你理解背后的核心思想。
一、基础铺垫:加法与乘法的时间复杂度
在研究大数乘法前,我们先明确n 位二进制数(十进制同理)算术运算的时间复杂度基准,这是后续分析的基础。
1.1 小学加法:线性时间且最优
小学阶段的竖式加法,逐位相加并处理进位,其时间复杂度为Θ(n) ,这是线性时间 。更重要的是,加法算法的下界是 Ω(n) ,即小学加法是最优算法 ,无法被优化到亚线性时间。证明核心:任何加法算法必须读取所有输入位。若存在未检查的位,翻转该位后算法会输出错误结果,因此加法的时间复杂度无法突破线性。
1.2 小学乘法:平方时间的瓶颈
小学竖式乘法的思路是:用一个数的每一位去乘另一个数的每一位,得到中间结果后逐位错位相加。对于两个 n 位数字,需要进行n×n 次位乘法 ,再加上错位相加的线性操作,整体时间复杂度为Θ(n²) ,这是二次时间。
二次时间的问题在于,当 n(数字的位数)足够大时,运算量会呈平方级爆炸式增长。比如 1000 位的大数相乘,小学方法需要约 100 万次运算,而 10000 位的大数相乘则需要 1 亿次运算,效率极低。
自然会产生两个问题:
- 大数乘法能否做到线性时间?(目前学术界尚无答案)
- 能否突破 Θ(n²) 的二次时间壁垒?(答案是肯定的,这就是后续要讲的核心)
二、高斯的经典优化:少一次乘法,省25%工作量
在进入大数乘法的分治优化前,先看高斯在复数乘法中提出的经典技巧,这是后续 Karatsuba 算法的核心灵感来源。
2.1 复数乘法的原始计算
两个复数 a+bi 和 c+di 相乘的结果为:(a+bi)(c+di)=(ac−bd)+(ad+bc)i要得到结果的实部和虚部,原始方法需要 4 次实数乘法(ac、bd、ad、bc)+ 少量加减法。若乘法成本为1,加法为1,原始成本为4.02。
2.2 高斯的3次乘法优化
高斯通过变形,将乘法次数从 4 次减少到 3 次,仅需3.05即可完成计算,节省 25% 的工作量:
- 计算 X1=(a+b)×c
- 计算 X2=a×(c+d)
- 计算 X3=b×d
- 实部:ac−bd=X2−X3−(X1−ac−X3)=X2−X1
- 虚部:ad+bc=X1−X3
核心思想 :用加减法的低代价,换取乘法的高代价减少,这是所有乘法优化算法的核心思路。
三、简单分治乘法的失败
既然直接的竖式乘法是 Θ(n²),我们尝试用分治思想拆解问题:将大数拆分为小数,递归求解后合并结果。
3.1 大数的分治拆解
对于两个 n 位大数 X 和 Y,将其各拆分为高 n/2 位和低 n/2 位:X=a×2n/2+b,Y=c×2n/2+d其中 a、b、c、d 均为 n/2 位数字,二者的乘积可展开为:X×Y=ac×2n+(ad+bc)×2n/2+bd
3.2 分治乘法的递归实现
基于上述展开式,分治乘法的递归算法(MULT)如下:
MULT(X, Y):
若X和Y均为1位数字,直接返回X×Y
否则将X拆分为a(高n/2位)、b(低n/2位),Y拆分为c(高n/2位)、d(低n/2位)
返回 MULT(a,c)×2^n + (MULT(a,d) + MULT(b,c))×2^{n/2} + MULT(b,d)
3.3 简单分治乘法仍为Θ(n²)
为该算法建立递推关系(忽略常数,简化为 T (1)=1):T(n)=4×T(n/2)+n其中:
- 4×T (n/2):递归调用 4 次 n/2 位的乘法(ac、ad、bc、bd)
- n:拆分和合并的线性时间(移位、加法)
递推求解 :用树状展开法分析,每一层的运算量为4i×n/2i=2i×n,总层数为log2n,总运算量为:T(n)=n×(1+2+4+...+n)=2n2−n=Θ(n2)
结论:分治只是改变了计算形式,并未减少乘法次数,因此时间复杂度仍为二次。
四、Karatsuba算法突破平方壁垒
1962年,Anatolii Alexeevich Karatsuba 将高斯的3次乘法优化 与分治思想 结合,提出了Karatsuba 算法,首次突破了Θ(n²) 的二次时间壁垒,这是大数乘法算法的里程碑。
4.1 将4次递归减为3次
Karatsuba 发现,分治乘法中最耗时的是4次递归乘法 ,而其中的ad+bc可以通过高斯技巧变形,仅用3次递归乘法实现:已知 X×Y=ac×2n+(ad+bc)×2n/2+bd,令:
- e=ac=MULT(a,c)(第 1 次递归)
- f=bd=MULT(b,d)(第 2 次递归)
- g=(a+b)×(c+d)=MULT(a+b,c+d)(第 3 次递归)
则中间项 ad+bc=g−e−f,因此乘积可重写为:X×Y=e×2n+(g−e−f)×2n/2+f
4.2 递归实现
Karatsuba(X, Y):
若X和Y均为1位数字,直接返回X×Y
否则将X拆分为a(高n/2位)、b(低n/2位),Y拆分为c(高n/2位)、d(低n/2位)
e = Karatsuba(a, c)
f = Karatsuba(b, d)
g = Karatsuba(a+b, c+d)
中间项 = g - e - f
返回 e×2^n + 中间项×2^{n/2} + f
4.3 时间复杂度提升至Θ(n^log₂3) ≈ Θ(n^1.58)
为 Karatsuba 算法建立递推关系(T (1)=1):T(n)=3×T(n/2)+n其中:
- 3×T (n/2):仅 3 次递归乘法(e、f、g)
- n:拆分、加法、减法、移位的线性时间
递推求解:同样用树状展开法,每一层的运算量为3i×n/2i=n×(3/2)i,总层数为log2n,总运算量为:T(n)=n×[1+3/2+(3/2)2+...+(3/2)log2n]=3nlog23−2n=Θ(nlog23)
log23≈1.58,因此 Karatsuba 算法的时间复杂度为Θ(n^1.58) ,这是超线性、亚二次的时间复杂度,当 n 足够大时,效率远高于小学乘法的 Θ(n²)。
比如 10000 位大数相乘:
- 小学方法:约 10^8 次运算
- Karatsuba 算法:约 10^(1.58×4) = 10^6.32 ≈ 208 万次运算,效率提升近 50 倍。
五、大数乘法的算法演进与后续发展
大数乘法的时间复杂度不断被优化,其演进路径如下:
- 幼儿园方法:Θ(n²)(最朴素的逐位相乘)
- 小学竖式乘法:Θ(n²)(标准化的逐位相乘 + 错位相加)
- 初版分治乘法:Θ(n²)(形式创新,无本质优化)
- Karatsuba 算法:Θ(n^1.58)(首次突破二次壁垒,工程中最常用)
- 目前已知最快算法:Θ(n logn loglogn)(理论上的极致,实现复杂度极高)
核心规律 :所有高效的大数乘法算法,都遵循用低代价的加减法 / 移位,换取高代价的乘法次数减少的思路,而分治思想则是实现这一思路的核心框架。
六、总结
本文从基础的时间复杂度出发,梳理了大数乘法从小学方法到 Karatsuba 算法的核心演进,核心知识点可总结为:
- 小学加法是Θ(n)的最优算法,无法突破线性下界;
- 小学乘法的Θ(n²)是二次时间壁垒,初版分治无法突破;
- 高斯的复数乘法优化是关键灵感:3 次乘法替代 4 次乘法,用加减法换乘法;
- Karatsuba算法将高斯优化与分治结合,实现 Θ(n^1.58) 的亚二次时间,是工程中最实用的高效大数乘法算法;
- 大数乘法的优化核心:减少高代价的乘法次数,用低代价的加减法 / 移位弥补。
Karatsuba算法不仅解决了大数乘法的效率问题,更体现了计算机科学的核心思想:问题的拆解与转化------ 将复杂的大数问题拆分为简单的小数问题,通过局部优化实现全局的效率提升。这一思想也适用于排序、查找、图论等各类算法问题,是每一个程序员都需要掌握的核心思维。
附:Karatsuba 算法的适用场景
- 适合大位数的整数相乘(如密码学中的大素数相乘、大数据中的高精度计算);
- 对于小位数数字,小学乘法的常数更小,实际运行速度更快(Karatsuba 的递归和加减法会带来额外开销)。
本文基于 CMU 15-251《Great Theoretical Ideas in Computer Science》课程 Lecture23 内容整理。