目录
基本知识
1.按位与&:把参与运算的两个数对应的二进制位相与,只有对应的二进制均为1时,结果的对应位才为1,否则为0。如:9&5中9可以写成(00001001),5可以写成(00000101),那么9&5的运算结果为0000 0001,输出结果是1。
- 按位或|:把参与运算的两个数对应的二进制位相或,也就是只要对应的两个二进制位有一个为1时,其结果就为1。 如:9|5相当于00001001|00000101,运算结果是00001101,输出结果是13
3.按位异或^:把参与运算的两个数对应的二进制位相异或,当对应的二进制位上的数据字不相同时,结果对应为1时,否则为0。如:1^1=0,1^0=1,0^0=0,0^1=1 9^5相当于00001001^00000101,运算结果是00001100,输出结果是12
4.取反~:把运算数的各个二进制位按位求反。如:~9相当于~(0000 1001),运算结果为1111 0110。
5.左亿<<:把“<<”左边的运算数的各二进制位向左移若干位,“<<”右边的数是指定移动的位数,高位丢弃,低位补0。 如 :a<<4指把a的各二进位向左移动4位,如a=00000011(十进制为3),左移4位后为00110000(十进制48)。
6.友谊>>:把“>>”左边的运算数的各二进制位全部右移若干位,“>>”右边的数是指定移动的位数。如:设a=15,a>>2表示把00001111右移为0000 0011(十进制为3)。
位运算的常用方法
乘以(2)运算
int mulTwo(int n) { // 计算 n*2
return n << 1;
}
除以(2)运算
int divTwo(int n) { // 负奇数的运算不可用
return n >> 1; // 除以 2
}
乘以(2)的(m)次方
int mulTwoPower(int n, int m) { // 计算 n*(2^m)
return n << m;
}
除以(2)的(m)次方
int mulTwoPower(int n, int m) { // 计算 n*(2^m)
return n << m;
}
判断一个数的奇偶性。
bool isOddNumber(int n)
{
return n & 1;
}
取绝对值(某些机器上,效率比$ n > 0 ? n : -n$ 高)
int abs(int n) {
return (n ^ (n >> 31)) - (n >> 31);
/* n>>31 取得 n 的符号,若 n 为正数,n>>31 等于 0,若 n 为负数,n>>31 等于 - 1
若 n 为正数 n^0=0, 数不变,若 n 为负数有 n^-1
需要计算 n 和 - 1 的补码,然后进行异或运算,
结果 n 变号并且为 n 的绝对值减 1,再减去 - 1 就是绝对值 */
}
取两个数的最大值(某些机器上,效率比 (a > b ? a : b) 高)
int max(int a, int b) {
return b & ((a - b) >> 31) | a & (~(a - b) >> 31);
/* 如果 a>=b,(a-b)>>31 为 0,否则为 - 1 */
}
取两个数的最小值(某些机器上,效率比$ a > b ? b : a $高)
int min(int a, int b) {
return a & ((a - b) >> 31) | b & (~(a - b) >> 31);
/* 如果 a>=b,(a-b)>>31 为 0,否则为 - 1 */
}
判断符号是否相同
bool isSameSign(int x, int y) { // 有 0 的情况例外
return (x ^ y) >=
0; // true 表示 x 和 y 有相同的符号,false 表示 x,y 有相反的符号。
}
计算(2)的(n)次方
int getFactorialofTwo(int n) { // n > 0
return 1 << n; // 2 的 n 次方
}
判断一个数是不是 2 的幂
bool isFactorialofTwo(int n) {
return n > 0 ? (n & (n - 1)) == 0 : false;
// 当然你也可以使用下面这种更为简便的写法:
// return n > 0 && (n & (n - 1)) == 0;
/* 如果是 2 的幂,n 一定是 100... n-1 就是 1111....
所以做与运算结果为 0 */
}
对(2)的(n)次方取余
int quyu(int m, int n) { // n 为 2 的次方
return m & (n - 1);
/* 如果是 2 的幂,n 一定是 100... n-1 就是 1111....
所以做与运算结果保留 m 在 n 范围的非 0 的位 */
}
求两个整数的平均值
int getAverage(int x, int y) {
return (x + y) >> 1;
}
遍历一个集合的子集
int b = 0;
do {
// process subset b
} while (b = (b - x) & x);
以上内容搬运自OI Wiki,只是为了以后好找