用于乘以两个数的算法

时间:2016-01-09 10:05:19

标签: algorithm bits

我们必须将两个数字x和y相乘,但我们不能使用*运算符。

一种简单的方法是添加x,y次或添加y,x次,这很简单并且是线性的。

第二种方法是选择任意数字(比如x)并查看在该数字中设置的所有位,如果设置了第i位,则执行以下操作:

product +=y<<i//product is 0 initially and do this for all i.

显然对于32位数字,循环运行32次并且其时间复杂度是恒定的。

我的问题是,还有其他办法吗?记住我们不能使用*。

3 个答案:

答案 0 :(得分:2)

假设两个数字都是无符号的,可以做(这或多或少等同于你的第二种方式)

p = 0
while x > 0
    while x is even
        x = x / 2    // a shift right operation
        y = y + y    // a shift left operation
    x = x - 1
    p = p + y

该产品现在位于p

要了解为什么这是正确的,请考虑不变

product = p + x*y

它由算法中的所有循环维护。我们从p = 0开始,所以它在开始时结束,当x = 0时结束,所以我们必须得到product = p。

答案 1 :(得分:1)

在某些体系结构中,可以使用单个指令在单词中设置第一个/最后一个位。

E.g。 GCC具有__builtin_clz (unsigned int x),它返回X中前导0位的数量。

或者strings.h中有int ffs(int i),它返回单词i中第一个(最低有效)位集的位置。

使用其中一个,您只能枚举一个单词中的设置位。这可以减少所需的迭代次数。

#include <stdlib.h>
#include <stdio.h>
#include <strings.h>

int main(int argc, char** argv)
{
  if(argc >= 2) {
    int a = atoi(argv[1]);
    int b = atoi(argv[2]);
    printf("%i * %i = %i", a, b, a*b);
    int r = 0;
    while (a) {
      int i = ffs(a) - 1;
      a ^= 1<<i;
      r += b<<i;
    }
    printf(" = %i\n", r);
  }
}

使用此代码,乘法1048576 * 123 = 128974848将在单次迭代中完成,因为1048576 = 0x100000只有一位设置。

答案 2 :(得分:0)

在没有*

的情况下相乘

解决方案1有整数:

我假设您可以使用+

做一个循环:x + x + .. + x(y次)。或y + ... + y(x次)。

解决方案2:

分解所有内容,为每个数字0-9保留一张x * y表,并重现手动操作,就像在小学一样。

解决方案3:结合其他两个方面,最简单,最强大:

对于整数:以二进制方式执行

13 * 7:

1101 * 111 = 1101 + 11010 + 110100 = 1011011 = 91

处理器的工作方式就是这样。没有+,只有二进制操作(和,或,xor)

对于非整数:用管理0的整数

进行

对于负数:同样的事情,管理+/-

时间复杂度在32位时保持不变:这是无关紧要的,因为一切都是不变的。

一般的时间复杂度:二元运算非常有效:

位数= O(log n)

=&GT; x * y =&gt; O(log x)* O(log y)