涉及位运算的运算符如下表所示:
位运算的运算律:
负数的位运算
首先,我们要知道,在计算机中,运算是使用的二进制补码,而正数的补码是它本身,负数的补码则是符号位不变,其余按位取反,最后再+ 1 +1+1得到的, 例如:
15 ,原码:00001111 补码:00001111
− 15 ,原码:10001111 补码:11110001
那么对于负数的位运算而言,它们的操作都是建立在补码上的,得到的运算结果是补码,最后将补码结果转化成一个普通的十进制数结果。
但需要注意的是,对于有符号数的右移操作,不同的处理器架构可能有不同的规定。在某些架构中(如x86)
对有符号数执行算术右移(arithmetic right shift),则高位空出来的位置会补上符号位;
对于无符号数的右移操作,所有架构都遵循相同的规则:高位空出来的位置会补0。
例如对于− 15 ,其补码为11110001 右移一位( − 15 > > 1 )得到的是11111000 即− 8 其他的同理。
在大多数现代处理器上,无论是有符号数还是无符号数,左移操作总是将空出来的低位补0。
位运算的应用
位运算实现乘除法
将x左移一位实现× 2 将x 右移一位实现÷ 2
a < < 1 ≡ a ∗ 2
a > > 1 ≡ a / 2
两数交换
void swap(int &a,int &b){a ^= b;b ^= a;a ^= b;}
剖析其原理,对于a = a ∧ b ,则b = b ∧ ( a ∧ b )
根据交换律以及异或性质,得b = b ∧ b ∧ a = 0 ∧ a = a
同理a = ( a ∧ b ) ∧ a = 0 ∧ b = b 这样就实现了交换操作。
位运算判断奇偶数
我们知道,在二进制中,最低位决定了是奇数还是偶数,所以我们可以提取出最低位的值,即与1 相与即可实现目的,为0 则是偶数,为1 则是奇数。
- (x & 1) == 0,则x为偶数
- (x & 1) == 1,则x为奇数
// 判断一个数是否为奇数
bool isOdd(int x) {return x & 1 == 1
}
位运算实践快速幂
int power(int base, int exp) {int result = 1;while (exp > 0) {if (exp & 1) {result = (result * base) % MOD;}base = (base * base) % MOD;exp >>= 1;}return result;
}