2的幂
位运算用于2的整数次幂可以优化复杂度
//计算 n * (2^m)
int mulPowerOfTwo(int n, int m) {
return n << m;
}
//计算 n / (2^m)
int divPowerOfTwo(int n, int m) {
return n >> m;
}
注意:/
除法是向 0 取整,而右移是向下取整。
取绝对值
在某些机器上,效率比 n > 0 ? n : -n
高。
int abs(int n) {
return (n ^ (n >> 31)) - (n >> 31);
}
int
类型占32位,n >> 31
取得 n 的符号,若 n 为正数,结果为 0,若 n 为负数,则结果为 -1。
若 n 为正数,(n ^ 0) - 0
仍是 n;
若 n 为负数,(n ^ -1) - -1)
相当于对 n 按位取反末尾加 1。
取两个数的最大/最小值
在某些机器上,效率比 a > b ? a : b
高。
// 如果 a >= b, (a - b) >> 31 为 0,否则为 -1
int max(int a, int b) {
return (b & ((a - b) >> 31)) | (a & (~(a - b) >> 31));
}
int min(int a, int b) {
return (a & ((a - b) >> 31)) | (b & (~(a - b) >> 31));
}
判断两非零数符号是否相同
bool isSameSign(int x, int y) { //有 0 的情况除外
return (x ^ y) >=0
}
交换两个整数
void swap(int &a, int &b) {
a ^= b;
b ^= a;
a ^= b;
}
但其实不推荐使用这种方式,推荐临时变量法:
void swap(int &a, int &b) {
int tmp = a;
a = b;
b = tmp;
}
对于临时变量法,每次赋值只要读取一个变量的值到寄存器,然后再从寄存器写回到另一个变量中即可,前后涉及两次内存操作;对于异或运算,每次都需要读取两个数据到寄存器中。然后进行运算,将结果写回变量中,前后共需三次内存操作。另外就是异或操作的代码可读性差。
操作一个数的二进制位
// 获取一个数二进制的某一位
// 获取 a 的第 b 位,最低位编号为 0
int getBit(int a, int b) {
return (a >> b) & 1;
}
// 将一个数二进制的某一位设置为0
// 将 a 的第 b 位设置为 0 ,最低位编号为 0
int unsetBit(int a, int b) {
return a & ~(1 << b);
}
//将一个数二进制的某一位设置为 1
// 将 a 的第 b 位设置为 1 ,最低位编号为 0
int setBit(int a, int b) {
return a | (1 << b);
}
//将一个数二进制的某一位取反
// 将 a 的第 b 位取反 ,最低位编号为 0
int flapBit(int a, int b) {
return a ^ (1 << b);
}
汉明权重
汉明权重是一串符号中不同于(定义在其所使用的字符集上的)零符号(zero-symbol)的个数。对于一个二进制数,它的汉明权重就等于它 1 的个数(即 popcount)。
求一个数的汉明权重可以循环求解:我们不断地去掉这个数在二进制下的最后一位(即右移 1 位),维护一个答案变量,在除的过程中根据最低位是否为 1 更新答案。
代码如下:
// 求 x 的汉明权重
int popcount(int x) {
int cnt = 0;
while (x) {
cnt += x & 1;
x >>= 1;
}
return cnt;
}
求一个数的汉明权重还可以使用 lowbit 操作:我们将这个数不断地减去它的 lowbit4,直到这个数变为 0。
代码如下:
// 求 x 的汉明权重
int popcount(int x) {
int cnt = 0;
while (x) {
cnt++;
x -= x & -x;
}
return cnt;
}
标签:cnt,return,运算,权重,int,31,应用,汉明
From: https://www.cnblogs.com/hzyuan/p/17973619