我想在Python中实现Karatsuba's 2-split multiplication。但是,以表格
编写数字A=c*x+d
其中x是基数(令x = b ^ m)接近sqrt(A)的幂。
如果我甚至不能使用除法和乘法,我该如何找到x?我应该计算位数并将A向左移动一半的位数吗?
感谢。
答案 0 :(得分:4)
几乎。你不要将A移位数字的一半;你移位1.当然,这只有在基数是2的幂时才有效,因为基数10(例如)中的“移位”必须用乘法来完成。 (编辑:好吧,好吧,你可以乘以班次和加法。但它的功能更加简单,功能为2。)
如果您使用的是Python 3.1或更高版本,则计算位很容易,因为3.1引入了int.bit_length()
方法。对于其他版本的Python,您可以通过复制A并将其向右移动直到它为0来对位进行计数。这可以在O(log N)时间(N =数字的数字)中使用一种二进制搜索方法完成 - 转换为很多位,如果它是0则那么太多,等等。
答案 1 :(得分:3)
自从我开始写这篇文章以来,你已经接受了答案,但是:
汤姆说:在Python 3.x中你可以直接得到n = int.bit_length()。 在Python 2.x中,你通过二进制搜索得到n(log2(A))时间,如下所示。
这是计算两者的(2.x)代码。设x的base-2指数为n,即x = 2 ** n。
首先,通过移位进行二元搜索得到n。 (实际上我们只需要n / 2,所以这是一次不必要的最后一次迭代)。 然后当我们知道n时,获得x,c,d很容易(仍然没有使用除法)
def karatsuba_form(A,n=32):
"""Binary-search for Karatsuba form using binary shifts"""
# First search for n ~ log2(A)
step = n >> 1
while step>0:
c = A >> n
print 'n=%2d step=%2d -> c=%d' % (n,step,c)
if c:
n += step
else:
n -= step
# More concisely, could say: n = (n+step) if c else (n-step)
step >>= 1
# Then take x = 2^(n/2) ˜ sqrt(A)
ndiv2 = n/2
# Find Karatsuba form
c = (A >> ndiv2)
x = (1 << ndiv2)
d = A - (c << ndiv2)
return (x,c,d)
答案 2 :(得分:2)
您提到的文章已经回答了您的问题:“Karatsuba的基本步骤适用于任何基数B和任何m,但当m等于n / 2时,递归算法效率最高,向上舍入”.. 。n
是位数,0&lt; = value_of_digit&lt;乙
可能有所帮助的一些观点:
您被允许(并且必须!)在学校算术中使用基本操作,例如number_of_digits // 2
和divmod(digit_x * digit_x, B)
...,其中B为10,您需要(例如)知道divmod(9 * 8, 10)
生成(7, 2)
。
在计算机上实现大数字运算时,通常使B成为2的最大幂,可以方便地支持基本乘法运算。例如,在32位机器上的CPython实现中,B被选择为2 ** 15(即32768),因为product = digit_x * digit_y; hi = product >> 15; lo = product & 0x7FFF;
工作时没有溢出而没有关注符号位。
我不确定你在Python中使用B == 2实现了什么,数字由Python int表示,其在C中的实现已经使用Karatsuba算法来乘以足够大的数字让它值得。它不可能是速度。
作为学习练习,您可能希望尝试将数字表示为数字列表,其中基数B是输入参数。