关于多项式的乘法。
假设A = 4526,B = 347,如何求解A * B ?
常规计算方式
通过小学掌握的知识,我们可以知道用上图中的计算方式可以求出A*B的值。但是,当A和B的数字非常非常大的时候(A/B均大于10位数),这个计算方式就显得冗余和复杂了。
那么为了简便的计算出A*B的结果,我们可以试着用上一课中学到的概念将A和B分解为更小的数字,然后将分解后的数字相乘,最后再把所有结果相加。
用Divide and Conquer来计算
A = 4526 --> 45 | 26 --> A = 45 * 10^2 + 26
B = 347 --> 03 | 47 --> B = 3 * 10^2 + 47
假设n=数字的位数,那么我们可以推理出以下公式:
A = a * 10^(n/2) + b
B = c * 10^(n/2) + d
A*B = (a * 10^(n/2) + b) * (c * 10^(n/2) + d)
= (a * 10^(n/2))(c * 10^(n/2)) + ad * 10^(n/2) + bc * 10^(n/2) + bd
= ac * 10^2(n/2) + (ad + bc) * 10^(n/2) + bd
因此要计算出A*B的值,我们每次需要做4次乘法,ac, ad, bc, bd.
A = 4526 --> 45 | 26
B = 347 --> 3 | 47n = 4
-------
ac = 45 * 3 --> 4 | 5 * 0 | 3 --> 0 * 10^2 + (12+0)*10 + 15 = 135
ad = 45 * 47--> 4 | 5 * 4 | 7 --> 16 * 10^2 + (28+20)*10 + 35 = 2115
bc = 26 * 3 --> 2 | 6 * 0 | 3 --> 0 * 10^2 + (6+0)*10 + 18 = 78
bd = 26 * 47 --> 2 | 6 * 4 | 7 --> 8 * 10^2 + (14+24)*10 + 42 = 1222
-------
A*B = ac * 10^4 + (ad + bc) * 10^2 + bd
= 135*10^4 + (2115 + 78) * 10^2 + 1222
= 1350000 + 219300 + 1222
= 1570522
如何再进一步简化,做更少的乘法运算呢?此时我们就要介绍Karatsuba的算法了:
Karatsuba Approach
针对ad + bc,我们需要做两次乘法(a*d和b*c),而Karatsuba提出实际上只需要做一次乘法就可以得ad + bc的结果,即只需要求(a+b)(c+d)。
因为:(a+b)(c+d) = ac + ad + bc + bd,再减去 ac 和 bd 后,就等于 ad + bc。(而由于ac和bd是本来就要计算的值,所以实际上只计算了一次乘法即(a+b)*(c+d) )
因此,最后的公式为:
A*B = ac * 10^2(n/2) + ((a+b)(c+d) - ac - bd) * 10^(n/2) + bd
A = 4526 --> 45 | 26
B = 347 --> 3 | 47n = 4
-------
ac = 45 * 3 --> 4 | 5 * 0 | 3 --> 0 * 10^2 + (12+0)*10 + 15 = 135
(a+b)(c+d) = 71 * 50 --> 7 | 1 * 5 | 0 --> 35 * 10^2 + (0+5)*10 + 0 = 3550
bd = 26 * 47 --> 2 | 6 * 4 | 7 --> 8 * 10^2 + (14+24)*10 + 42 = 1222
-------
A*B = ac * 10^2(n/2) + ((a+b)(c+d) - ac - bd) * 10^(n/2) + bd
= 135*10^4 + (3550 - 135 - 1222) * 10^2 + 1222
= 1350000 + 219300 + 1222
= 1570522
Implementation
in python3
def karatsuba(A, B):
if A < 10 or B < 10:
return A * B
else:
n = max(len(str(A)), len(str(B)))
half = n // 2
a = A // (10 ** (half)) # left part of A
b = A % (10 ** (half)) # right part of A
c = B // (10 ** (half)) # left part of B
d = B % (10 ** (half)) # right part of B
ac = karatsuba(a, c)
bd = karatsuba(b, d)
ad_plus_bc = karatsuba(a+b, c+d)-ac-bd
return ac * (10 ** (2 * half)) + (ad_plus_bc * (10 ** half)) + bd
A = int(input('Enter A:'))
B = int(input('Enter B:'))
print('A * B =', karatsuba(A,B))