异想时刻
在做数字运算的时候,常常会遇到结果溢出的情形,也就是超出了整型所能表达的最大数字。此时便不能通过整型去表达数字了,需要以字符串的形式来存储和计算数字。以下记录下几种大数乘法的运算方法以便后续应用。
普通算法
采用按位相乘错位相加的方式计算结果。若针对两个n位数的整数,其时间复杂度为。以56*34为例。
1 2 3 4 5 6 7 8 9
| 5 6 x 3 4 --------- 20 24 15 18 --------- 15 38 24 --------- 1 9 0 4
|
Karatsuba算法
卡拉楚巴算法是一种快速乘法算法,它由阿纳托利·阿列克谢耶维奇·卡拉楚巴于1960年提出并于1962年发表。若针对两个n位数的整数,其时间复杂度为。相对于普通的经典算法,在性能上有了很大的提高。
原理剖析
以为例,x的位数,y的位数,x和y可以表达为
=>
=>
可以看出,只需要做三次乘法便可求出系数。递归以上过程,直到
伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| procedure karatsuba(x, y) { if(x<10||y<10) return x*y; int n1 = len(x), n2=len(y); int n = max(n1, n2); int m = floor(n/2); x0, x1 = split(x, m); y0, y1 = split(y, m); z0 = karatsuba(x0, y0); z2 = karatsuba(x1, y1); z1 = karatsuba(x0+x1, y0+y1)-z0-z2; return z0*10^(2*m)+z1*10^m+z2; }
|
Schönhage–Strassen 算法
颂哈吉-施特拉森算法是渐近快速的大整数乘法算法,由阿诺德·颂哈吉和沃尔克·施特拉森在1971年发明。算法采用快速傅里叶变换,对数字进行数论转换,可以快速计算出两个大数的乘积。若针对两个n位数的整数,其时间复杂度为。
傅里叶变换
傅里叶变换是一种线性积分变换,常用于信号在时域和频域间的变换。傅里叶变换是可逆的,可通过转换后的复函数还原成实函数。
连续傅里叶变换
将一组函数映射到另一组函数,其表现形式如下
a为常规化因子,由使用者自主选择,不同领域取值不一。
逆变换形式为:
离散傅里叶变换DFT
对于N点序列的离散傅里叶变换为
逆变换,
原理剖析
此算法采用了数论DFT来计算两个数的乘积。注意并不是直接使用DFT,在计算时需要进行一次数论变换。为什么?由于快速傅里叶变换是复数运算,这样就存在大量的浮点数运算。不仅会导致计算性能低,而且运算结果也会存在较大的偏差。
经过数论转换后的DFT形式如下。
逆变换,
其中,
1,M是一个质数
2,N是M-1的因子
3,
4,
计算步骤
Step 1, 将相乘的两项转化为两个向量,比如1234*5678,变换后为和,向量的维数为两个数的位数之和。
Step 2, 对X和Y进行快速傅里叶变换。以下为具体的转换流程。
=>
Step 3, 对X和Y按为相乘,并对M取模,得到向量Z。然后求取Z的DFT逆变换,得到向量z。
=>
Step 4, 逐项遍历z,对每一项超过10的部分进行进位累加到下一项中,直到遍历结束。将z倒置便得到最终结果。
Pic1展示了算法的整个计算过程。

References:
[1]https://zh.wikipedia.org/zh-cn/%E5%8D%A1%E6%8B%89%E6%A5%9A%E5%B7%B4%E7%AE%97%E6%B3%95
[2]https://zh.wikipedia.org/zh-cn/%E9%A0%8C%E5%93%88%E5%90%89-%E6%96%BD%E7%89%B9%E6%8B%89%E6%A3%AE%E6%BC%94%E7%AE%97%E6%B3%95
[3]https://zh.wikipedia.org/zh-cn/%E6%95%B8%E8%AB%96%E8%BD%89%E6%8F%9B
[4]https://zh.wikipedia.org/zh-cn/%E6%A8%A1%E5%8F%8D%E5%85%83%E7%B4%A0
[5]https://zh.wikipedia.org/zh-cn/%E5%BF%AB%E9%80%9F%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2
[6]https://zh.wikipedia.org/zh-cn/%E7%A6%BB%E6%95%A3%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2
[7]https://zh.wikipedia.org/wiki/%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2
[8]https://zh.wikipedia.org/wiki/%E8%BF%9E%E7%BB%AD%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2