Karatsuba乘法的算法思路运用了递归的思想,贴上Stanford的Tim Roughgarden的课件。这里说说我遇到的代码实现的问题。
在coursera上面的算法课的作业题是用这个Karatsuba做两个64位整数相乘。
我最开始写的代码:
import numpy as np
def Karatsuba(x,y):
m=(len(str(x))//2)
a = x // (np.power(10, m))
b = x % np.power(10, m)
c = y // (np.power(10, m))
d = y % np.power(10, m)
if len(str(x))==1:
return x*y
else:
a_c = Karatsuba(a,c)
b_d = Karatsuba(b,d)
ad_bc = Karatsuba(a+b,c+d) - a_c - b_d
res = np.power(10,m*2) *a_c +np.power(10,m)*ad_bc + b_d
return res
当输入不太大的时候,例如8位或者16位整数,代码实现没有问题,但是当输入为64位数的数字时,代码就会报错,如
RecursionError: maximum recursion depth exceeded while calling a Python object
或者
RuntimeWarning: overflow encountered in long_scalars.
问题在于实现10^n次方时选择numpy.power(10,n), 需要修改为10**n,正确的代码如下:
def Karatsuba(x,y):
m=(len(str(x))//2)
a = x // 10 ** m
b = x % 10 ** m
c = y // 10 ** m
d = y % 10 ** m
if len(str(x))==1:
return x*y
else:
a_c = Karatsuba(a,c)
b_d = Karatsuba(b,d)
ad_bc = Karatsuba(a+b,c+d) - a_c - b_d
res = 10**(2*m)*a_c + 10**m*ad_bc +b_d
return res
同样的,我之前也尝试过用math.pow(10,n)来表示10的n次方 ,在递归时输入太大也会报错。
所以总结就是多用10**n,其次numpy.power(10,n)【因为内置函数是c语言实现的,比较快】,最次math.pow(10,n)。
大家可以练习一下啦~ (有错欢迎纠正指教~)
输入:
s1=3141592653589793238462643383279502884197169399375105820974944592 s2=2718281828459045235360287471352662497757247093699959574966967627
你的输出是多少呢?
(PS:其实在python中输入s1*s2 就可以直接得到正确答案, 可以和自己的代码结果比较)