如何使用位操作来计算乘法

302 阅读4分钟

我们已经解释了如何使用位操作来计算乘法。我们可以使用左移、右移和否定位操作来解决这个问题。

内容表

  1. 使用位操作的乘法运算
  2. 用2个步骤的例子进行解释
  3. 使用比特运算实现乘法
  4. 时间和空间的复杂性

让我们开始学习顺位乘法。

使用比特运算的乘法运算

问题

要找到两个数字num1num2 的乘法,使用位运算。

我们将使用俄罗斯农民的乘法方法来解决这个问题。

基本条款:

  • a×b = (a×2)×(b/2)
  • 如果b 是偶数,那么a×b = (a×2)×(b/2)
  • 如果b 是奇数,那么a×b = ((a×2)×(b/2) + a)

乘法的步骤:

  • 在一个循环内(执行到b>=1)。
    • 我们不断地将a 乘以2,并不断地将b 除以2。
    • 如果b 是奇数,那么,result+=a
    • a 乘以2,再将b 除以2。
    • b == 1 ,答案将是result + a

算法

假设我们得到了两个数字num1num2

  • 初始化变量result 为0
    • 重复这个过程,直到num2 大于0
      • 如果num2 是奇数,则将num1 加到result
      • num2 减半,并使用位移运算符将num1 加倍。
  • 打印result

用2个步骤的例子进行解释

例1:正数x正数

让我们取a = 4b = 5
,因为这两个数字都是正数,然后a = 4 (0b 0000100)b = 5 (0b 000101)
进行初始化

result = 0

  • 第一次迭代:由于b 是奇数,那么result = 4 (结果+=4),a = 8 (0b 000100)b = 2 (0b 000010)
  • 第二次迭代:当b 是偶数时,result = 4,a = 16 (0b 001000)b = 1 (0b 000001)
  • 第3次迭代:当b 是奇数时,result = 20 (结果+=16),a = 32 (0b 010000)b = 0 (0b 000000)
  • 由于b==0 (0b 000000) 循环将停止,我们将得到result = 20

例2:正数 x 负数

让我们把a = 4b = -5

如果其中任何一个数字是负数,那么我们将设置一个布尔变量neg=true
,并将两个数字都设置为正数
,然后
a = 4 (0b 0000100)b = 5 (0b 000101)
初始化

result = 0

  • 第一次迭代:当b 是奇数时,result = 4 (结果+=4),a = 8 (0b 000100)b = 2 (0b 000010)

  • 第二次迭代:当b 是偶数时,result = 4,a = 16 (0b 001000)b = 1 (0b 000001)

  • 第3次迭代:当b 是奇数时,result = 20 (结果+=16),a = 32 (0b 010000)b = 0 (0b 000000)

  • 由于b==0 (0b 000000) 循环将停止,并且由于neg=true,我们将返回result = 20

    的2的补数
    ,即-20

    [(~(result)+1)]

使用位操作实现乘法

以下是使用位操作实现乘法的方法:

#include<iostream>
using namespace std;

int multiply_bitewise(int a, int b)
{
  int n1 = abs(a), n2 = abs(b), result = 0;
  bool neg = false;
  if(min(a,b)<0 && max(a, b)>=0) neg=true;
  while(n2>0)
  {
    if(n2&1==1) result+=n1;
    n2>>=1; n1<<=1;
  }
  if(neg) return (~(result)+1);
  else return result;
}

int main()
{
  cout<<multiply_bitewise(4, 5)<<endl;
  cout<<multiply_bitewise(4, -5)<<endl;
  cout<<multiply_bitewise(-4, 5)<<endl;
  cout<<multiply_bitewise(-4, -5)<<endl;
  return 0;
}

你也可以用位加法代替上面代码中的加法运算。你可以在这里了解顺位加法

输出

20
-20
-20
20

时间和空间复杂度

时间复杂度

我们的乘法算法的时间复杂度是。O(logN * logN)

其中:

  1. N是要乘的数字。
  2. logN是用来表示N的比特数。

这是因为对数N位,对于每一个位,我们做一系列的步骤,其中包括一个加法,其时间复杂度为O(logN)。

由于系统中的数据类型的位数是固定的(例如整数的32位),那么logN=32,因此,乘法在这方面被认为是一个常数操作。

使用乘法的最佳算法,时间复杂度将是O(logN loglogN)。你可以在这里了解更多关于乘法算法的信息。

注:这种优化算法在2019年被发现,人们普遍认为它已经达到了理论极限,但还没有被证明。

空间复杂度

位数乘法的空间复杂度是:O(1)
位数乘法过程中没有产生额外的空间。

通过OpenGenus的这篇文章,你一定对位数乘法有了完整的认识。好好享受吧。