|

楼主 |
发表于 2020-10-9 18:00
|
显示全部楼层
本帖最后由 ysr 于 2020-10-9 14:56 编辑
我们以两个 3 ( N = 3 ) 位数 a = 678 和 b = 432 的乘积来说明以上过程吧。
a = (678)'10 = 6x10^2 + 7x10^1 + 8x10^0
b = (432)'10 = 4x10^2 + 3x10^1 + 2x10^0
由此:
c = a x b = 10^4xc4 + 10^3xc3 + 10^2xc2 + 10^1xc1 + 10^0xc0
= 10000x24 + 1000x46 + 100x65 + 10x38 + 1x16
= 292896
如果按以上方法计算大整数的乘法,时间复杂度是 O(N^2)。
在我们的例子中,乘积 c = 292896,共 6 位数字,N 需要扩展到 2^3 = 8。那么,向量 {ai} 和向量 {bj} 如下所示:
{ a7, a6, a5, a4, a3, a2, a1, a0 } = { 0, 0, 0, 0, 0, 6, 7, 8 }
{ b7, b6, b5, b4, b3, b2, b1, b0 } = { 0, 0, 0, 0, 0, 4, 3, 2 }
ω^0~ω^7分别是1,0.7-0.7i,-i,-0.7-0.7i,-1,-0.7+0.7i,i,0.7+0.7i.
可见ω^1和ω^7是共轭的,ω^2和ω^6是共轭的,等,这就是对称性。
ω^0和ω^8是相等的,ω^4和ω^12是相等的,等,这就是周期性。
向量A0就是8,7,6依次乘以ω^0,再加起来得到21.
以此类推得到:
{ A7, A6, A5, A4, A3, A2, A1, A0 } = { 12.9+10.9i, 2+7i, 3.1-1.1i, 7, 3.1+1.1i, 2-7i, 12.9-10.9i, 21 }
{ B7, B6, B5, B4, B3, B2, B1, B0 } = { 4.1+6.1i, -2+3i, -0.1-1.9i, 3, -0.1+1.9i, -2-3i, 4.1-6.1i, 9 }
现在,将她们逐项相乘得到向量 {Ck},即 { C7, C6, C5, C4, C3, C2, C1, C0 }
= { -13.6+123.4i, -25-8i, -2.4-5.8i, 21, -2.4+5.8i, -25+8i, -13.6-123.4i, 189 }
这一步好像就是把前两个向量的对应项相乘得到的。
这样,我们就使用离散傅里叶变换和逆变换计算出了向量 {ai} 和向量 {bj} 的卷积向量 {ck},如下所示:
{ c7, c6, c5, c4, c3, c2, c1, c0 } = { 0, 0, 0, 0, 24, 46, 65, 38, 16 }
这些两位数错位相加,就得到292896。
问题是如何利用对称性和周期性?使这个算法的时间复杂度由 O(N^2),变成O(N logN)?
ω是如何计算的呢?
为了计算离散傅里叶变换,如当N=8时,我们令:
ω = e^(-2πi/N )= e^(-2πi/8) = e^(-πi/4) = cos(-π/4) + i sin(-π/4) = √2 / 2 - i √2 / 2 ≈ 0.7-0.7i
而ω^0~ω^8都以此为基础,以此类推,如ω^0=e^0=1,
ω^1=e^(-πi/4) = cos(-π/4) + i sin(-π/4) = √2 / 2 - i √2 / 2 ≈ 0.7-0.7i,
ω^2=e^(-πi/2)=0+i*(-1)=-i,
……。
这就是快速离散傅里叶变换在大数乘法中的应用。
|
|