目录
[1. 按位与(AND)`&`:](#1. 按位与(AND)&
:)
[2. 按位或(OR)`|`:](#2. 按位或(OR)|
:)
[3. 按位异或(XOR)`^`:](#3. 按位异或(XOR)^
:)
[4. 按位取反(NOT)`~`:](#4. 按位取反(NOT)~
:)
[5. 左移(Left Shift)`<<`:](#5. 左移(Left Shift)<<
:)
[1. 快速乘除以2的幂:](#1. 快速乘除以2的幂:)
[2. 交换两个数(不使用临时变量):](#2. 交换两个数(不使用临时变量):)
[3. 检测奇偶性:](#3. 检测奇偶性:)
[4. 清除最低位的1:](#4. 清除最低位的1:)
[5. 获取最低位的1:](#5. 获取最低位的1:)
[6. 统计二进制中1的个数:](#6. 统计二进制中1的个数:)
[7. 快速判断是否是2的幂:](#7. 快速判断是否是2的幂:)
[1. 设置某一位:](#1. 设置某一位:)
[2. 清除某一位:](#2. 清除某一位:)
[3. 切换某一位:](#3. 切换某一位:)
[4. 检查某一位是否为1:](#4. 检查某一位是否为1:)
[5. 计算二进制中1的个数:](#5. 计算二进制中1的个数:)
摘要
在C++中,位操作可以通过位与(AND )、位或(OR )、位异或(XOR )、位取反(NOT )、左移(Left Shift )和右移(Right Shift)等操作来实现。如果结合宏定义来使用,可以使位操作更加简洁。
基本位操作
1. 按位与(AND )`&`:
每个位进行与运算,只有对应位都为1时,结果位才为1。
cpp
int a = 5; // 0101
int b = 3; // 0011
int result = a & b; // 0001 -> 1
2. 按位或(OR )`|`:
每个位进行或运算,只要对应位有一个为1,结果位就为1。
cpp
int a = 5; // 0101
int b = 3; // 0011
int result = a | b; // 0111 -> 7
3. 按位异或(XOR )`^`:
cpp
int a = 5; // 0101
int b = 3; // 0011
int result = a ^ b; // 0110 -> 6
每个位进行异或运算,对应位相同为0,不同为1。
4. 按位取反(NOT )`~`:
将每个位取反,0变1,1变0。
cpp
int a = 5; // 0101
int result = ~a; // 1010 -> -6(在补码表示中)
5. 左移(Left Shift)`<<`:
将二进制数的所有位向左移动指定的位数,右边补0。
cpp
int a = 5; // 0101
int result = a << 1; // 1010 -> 10
- 右移(Right Shift )`>>`:
将二进制数的所有位向右移动指定的位数,左边补符号位(算术右移)或0(逻辑右移)。
cpp
int a = 5; // 0101
int result = a >> 1; // 0010 -> 2
高级用法
1. 快速乘除以2的幂:
左移操作相当于乘以2的幂,右移操作相当于除以2的幂。
cpp
int a = 5;
int result = a << 3; // 相当于 a * 8 -> 40
result = a >> 2; // 相当于 a / 4 -> 1
2. 交换两个数(不使用临时变量):
可以使用异或操作来交换两个数。
cpp
int a = 5;
int b = 3;
a = a ^ b;
b = a ^ b;
a = a ^ b;
// 现在 a = 3, b = 5
3. 检测奇偶性:
使用按位与操作来检测一个数是奇数还是偶数。
cpp
int a = 5;
bool isOdd = a & 1; // 如果 a 的最后一位是1,则是奇数
4. 清除最低位的1:
通过 `x & (x - 1)` 可以清除最低位的1。
cpp
int a = 12; // 1100
int result = a & (a - 1); // 1000 -> 8
5. 获取最低位的1:
使用 `x & -x` 可以获取最低位的1。
cpp
int a = 12; // 1100
int result = a & -a; // 0100 -> 4
6. 统计二进制中1的个数:
可以通过反复清除最低位的1来统计一个整数中1的个数。
cpp
int countOnes(int x) {
int count = 0;
while (x) {
x = x & (x - 1);
count++;
}
return count;
}
7. 快速判断是否是2的幂:
一个数如果是2的幂,则它的二进制表示中只有一个1。
cpp
bool isPowerOfTwo(int x) {
return x > 0 && (x & (x - 1)) == 0;
}
与宏定义结合
通过将位操作与宏定义结合,可以提高代码的可读性和可维护性,同时保留位操作的高效性。
1. 设置某一位:
cpp
#define SET_BIT(x, pos) ((x) | (1 << (pos)))
int x = 5; // 0101
x = SET_BIT(x, 1); // 设置第1位 -> 0111 -> 7
2. 清除某一位:
cpp
#define CLEAR_BIT(x, pos) ((x) & ~(1 << (pos)))
int x = 7; // 0111
x = CLEAR_BIT(x, 1); // 清除第1位 -> 0101 -> 5
3. 切换某一位:
cpp
#define TOGGLE_BIT(x, pos) ((x) ^ (1 << (pos)))
int x = 5; // 0101
x = TOGGLE_BIT(x, 1); // 切换第1位 -> 0111 -> 7
x = TOGGLE_BIT(x, 1); // 再次切换第1位 -> 0101 -> 5
4. 检查某一位是否为1:
cpp
#define CHECK_BIT(x, pos) ((x) & (1 << (pos)))
int x = 5; // 0101
bool isSet = CHECK_BIT(x, 2); // 检查第2位 -> 0100 -> true
5. 计算二进制中1的个数:
cpp
#define COUNT_ONES(x) ({ \
int count = 0; \
int n = (x); \
while (n) { \
n &= (n - 1); \
count++; \
} \
count; \
})
int x = 15; // 1111
int onesCount = COUNT_ONES(x); // 4
总结
在C++中使用位操作一定需要注意自己的需求是什么,对位操作一定要仔细,否则很容易出现问题。同时,通过位操作可以优化代码,并且如果有涉及到一些算法的地方,也可以用位操作来优化算法,提高整体性能。