Karatsuba算法子问题

时间:2018-04-18 12:13:48

标签: algorithm binary multiplication karatsuba

我试图在乘以两个二进制值时找出关于Karatsuba算法的问题。我想成倍增加:

10110110 * 11001000

我需要弄清楚使用Karatsuba算法时完成哪些子问题。我知道算法是

x * y = ((2^n)(xHyH))+(2^(n/2))(xHyL + xLyH) + xLyL

但每个值代表什么?如何从二进制值转到xH,yH,xL,yL?感谢。

1 个答案:

答案 0 :(得分:0)

重点是将你的数字分成低位和高位:

x = 10110110b
xh= 1011b
xl=     0110b
x = xh<<4 + xl     

数字基数并不重要(但必须具有相同的基数),因为您处理Karatsuba中的数字,因此您可以使用任何基数。您只需要在所使用的基础上定义所需的操作。因此,例如,如果您的数字是十进制字符串,则无需将其转换为二进制。

所以关键是从第一次运行中将pad x,y从右边零填充到2位宽度的公共功率(如果还没有完成),或者在每次运行中只调整到通用大小以避免/处理舍入问题分裂时。由于数字通常是某种寄存器或编程语言变量类型,因此它们通常已经为零填充。如果是bignums或字符串,则无法保证。

然后在每一步中,将x,y分成两半并计算等式。

这些方程涉及乘法,所以它递归地调用相同的karatsuba乘法,但现在使用半位宽数字。

一旦达到x,y的可计算位宽,就直接计算乘法而不是使用Karatsuba(这通常是 ALU 支持乘法的最高字位宽度。)< / p>

当您输入x,y时,数字已经是8位,大多数 CPU 可以直接处理,不需要Karatsuba。如果你没有乘法或想要尝试这些东西,你可以细分到位宽1并使用真值表:

0*0=0
0*1=0
1*0=0
1*1=1

现在问题是你需要在可能超过其位宽的位置(在部分乘法之后)添加数字块。 (如果你添加两个4位数字,结果可能是9位)并且在Karatsuba方程式中你添加了很多东西,所以你需要记住你需要的不仅仅是单个进位(我认为两个应该削减它,我改为使用双增量(检查溢出两次),这适用于我)。

此外,如果您使用限制ALU位宽和更高级别的语言(如C / C ++),您可能根本无法进行携带,需要解决它,例如:

这里有小例子(以及其他一些方法):

如果您想要测量速度,请记住Karatsuba的开销比天真O(n^2)更大,但只有足够大的数字才会加倍......

现在回到你的分裂问题。全部取决于您的号码是如何存储的。所以在字符串的情况下,你用字符串函数分割它们。如果是数字,你可以将它们放在一个已经用二进制表示的变量中(在硅片级别上),这样你就可以使用位移和掩码。在C ++中8 -> 4 + 4位的情况下,它是这样完成的:

x = your number;
xl = x&15; // bitwise AND
xh = x>>4; // shift right arithmetic SRA by 4 bits

其中15 = (1<<4)-14是您要拆分的位宽。因此,如果您想要n位宽,则可以重写为:

x = your number;
n = new bit width (half of x bitwidth)
xl = x&((1<<n)-1); // bitwise AND
xh = x>>n; // shift right arithmetic SRA by 4 bits

您也可以将递归中的n作为操作数传递,然后将其加n>>=1一半,然后停在n=0上,这意味着您已经在1位宽度上并且没有理由拆分...