【问题标题】:Algorithm for multiplying two numbers两个数相乘的算法
【发布时间】:2016-04-14 00:36:34
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 根据您对精度的敏感程度以及允许使用的数字表示形式,您可能只需执行 x / (1 / y)
  • 这不适用于整数类型,polettix,除非您愿意对其进行调整以进行浮点运算(这会导致精度损失)。
  • 小心负数!
  • @polettix 忘了说,我们也不能使用 / 操作符。
  • @SumeetSingh 我建议也更新这个问题。

标签: algorithm bits


【解决方案1】:

在某些架构上,可以通过单条指令在一个字中设置第一个/最后一个位。

例如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】:

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

    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。

    【讨论】:

      【解决方案3】:

      没有*的乘法

      整数解决方案 1:

      我假设你可以使用 +

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

      解决方案 2:

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

      解决方案 3:结合其他两个并且最简单和健壮:

      对于整数:以二进制形式进行

      13 * 7:

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

      处理器就是这样工作的。没有+,只有二元运算(and,or,xor)

      对于非整数:使用管理 0 的整数进行操作

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

      时间复杂度在 32 位中是恒定的:这无关紧要,因为一切都是恒定的。

      一般的时间复杂度:二元运算相当高效:

      位数 = O(log n)

      => x*y => O(log x) * O(log y)

      【讨论】:

      • “没有+,只有二元运算(and,or,xor)”:这是什么意思?我知道的所有处理器都有add 机器指令。
      • @Henry "add" 机器指令是整数(通常为 8/16/32/64 位)的二进制运算或与协处理器或特定硬件、微处理器的浮点运算的结合代码或更微妙的算法。
      猜你喜欢
      • 1970-01-01
      • 2011-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      • 1970-01-01
      相关资源
      最近更新 更多