位运算的应用
提供一些关于位运算的函数应用,有C语言和Python语言两个版本
取绝对值
在一些机器上,位运算的效率要比n > 0 ? n : -n
高
左移右移
C++代码
int Abs(int n) {
return (n ^ (n >> 31)) - (n >> 31);
/* n>>31 取得 n 的符号,若 n 为正数,n>>31 等于 0,若 n 为负数,n>>31 等于 -1
若 n 为正数 n^0=n, 数不变,若 n 为负数有 n^(-1)
需要计算 n 和 -1 的补码,然后进行异或运算,
结果 n 变号并且为 n 的绝对值减 1,再减去 -1 就是绝对值 */
}
Python代码
def Abs(n):
return (n ^ (n >> 31)) - (n >> 31)
"""
n>>31 取得 n 的符号,若 n 为正数,n>>31 等于 0,若 n 为负数,n>>31 等于 -1
若 n 为正数 n^0=n, 数不变,若 n 为负数有 n^(-1)
需要计算 n 和 -1 的补码,然后进行异或运算,
结果 n 变号并且为 n 的绝对值减 1,再减去 -1 就是绝对值
"""
异或
int v; // we want to find the absolute value of v
unsigned int r; // the result goes here
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
r = (v + mask) ^ mask;
比较两个数的最大最小值
一般情况下效率比 a > b ? a : b
高。
C++
// 如果 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)); }
Python
# 如果 a >= b, (a - b) >> 31 为 0,否则为 -1
def max(a, b):
return b & ((a - b) >> 31) | a & (~(a - b) >> 31)
def min(a, b):
return a & ((a - b) >> 31) | b & (~(a - b) >> 31)
其他版本
int x; // we want to find the minimum of x and y
int y;
int r; // the result goes here
r = y ^ ((x ^ y) & -(x < y)); // min(x, y)
r = x ^ ((x ^ y) & -(x < y)); // max(x, y)
Quick and dirty versions
如果知道INT_MIN <= x - y <= INT_MAX,那么您可以使用下面的方法,它更快,因为(x - y)只需要计算一次。请注意,1989年的ANSIC规范没有指定带符号右移的结果,因此这些是不可移植的。如果在溢出时抛出异常,则x和y的值应该是无符号的,或者在减法时转换为无符号的,以避免不必要地抛出异常,但是右移需要一个有符号的操作数来产生所有的1位,所以在那里转换为有符号的。
r = y + ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1))); // min(x, y)
r = x - ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1))); // max(x, y)
交换两个数
这种方式只能用来交换两个整数,使用范围有限。
对于一般情况下的交换操作,推荐直接调用 algorithm 库中的 std::swap 函数。
void swap(int &a, int &b) { a ^= b ^= a ^= b; }
操作一个数的二进制位
获取一个数二进制的某一位:
C++
// 获取 a 的第 b 位,最低位编号为 0
int getBit(int a, int b) { return (a >> b) & 1; }
Python
# 获取 a 的第 b 位,最低位编号为 0
def getBit(a, b):
return (a >> b) & 1
将一个数二进制的某一位设置为 0 0 0:
C++
// 将 a 的第 b 位设置为 0 ,最低位编号为 0
int unsetBit(int a, int b) { return a & ~(1 << b); }
Pyhton
# 将 a 的第 b 位设置为 0 ,最低位编号为 0
def unsetBit(a, b):
return a & ~(1 << b)
将一个数二进制的某一位设置为 1 1 1:
C++
// 将 a 的第 b 位设置为 1 ,最低位编号为 0
int setBit(int a, int b) { return a | (1 << b); }
Pyhton
# 将 a 的第 b 位设置为 1 ,最低位编号为 0
def setBit(a, b):
return a | (1 << b)
将一个数二进制的某一位取反:
C++
// 将 a 的第 b 位取反 ,最低位编号为 0
int flapBit(int a, int b) { return a ^ (1 << b); }
Pyhton
# 将 a 的第 b 位取反 ,最低位编号为 0
def flapBit(a, b):
return a ^ (1 << b)