我们已经解释了如何使用位操作来计算乘法。我们可以使用左移、右移和否定位操作来解决这个问题。
内容表:
- 使用位操作的乘法运算
- 用2个步骤的例子进行解释
- 使用比特运算实现乘法
- 时间和空间的复杂性
让我们开始学习顺位乘法。
使用比特运算的乘法运算
问题
要找到两个数字num1 和num2 的乘法,使用位运算。
我们将使用俄罗斯农民的乘法方法来解决这个问题。
基本条款:
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
- 我们不断地将
算法
假设我们得到了两个数字num1 和num2
- 初始化变量
result为0- 重复这个过程,直到
num2大于0- 如果
num2是奇数,则将num1加到result - 将
num2减半,并使用位移运算符将num1加倍。
- 如果
- 重复这个过程,直到
- 打印
result
用2个步骤的例子进行解释
例1:正数x正数
让我们取a = 4 和b = 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 = 4 和b = -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)
其中:
- N是要乘的数字。
- logN是用来表示N的比特数。
这是因为对数N位,对于每一个位,我们做一系列的步骤,其中包括一个加法,其时间复杂度为O(logN)。
由于系统中的数据类型的位数是固定的(例如整数的32位),那么logN=32,因此,乘法在这方面被认为是一个常数操作。
使用乘法的最佳算法,时间复杂度将是O(logN loglogN)。你可以在这里了解更多关于乘法算法的信息。
注:这种优化算法在2019年被发现,人们普遍认为它已经达到了理论极限,但还没有被证明。
空间复杂度
位数乘法的空间复杂度是:O(1)
位数乘法过程中没有产生额外的空间。
通过OpenGenus的这篇文章,你一定对位数乘法有了完整的认识。好好享受吧。