位運算操作技巧
阿新 • • 發佈:2022-05-17
使用位運算的注意事項:
- 位操作只能用於整形資料,對float和double型別進行位操作編譯器會報錯。
- 位操作符的運算優先順序比較低,儘量使用括號來確保運算順序。
注意:一般運算不一定比位運算慢。編譯器已經做的很好了,會把一般運算優化為位運算。
某些自作聰明的優化反而會誤導編譯器,使得編譯器不進行更棒的優化。
取第n位的值(從右邊)
int r = (v >> n) & 1;
把某一位置1(從右邊)
v = v | (1 << n);
把某一位取反(從右邊)
v = v ^ (1 << n);
把最後一個1置0
v = v & (v - 1);
把最後一個0置1
v = v | (v + 1);
奇偶判斷
(v & 1)
計算絕對值
int bits = sizeof(v) * 8 - 1;
int r = (v ^ (v >> bits)) - (v >> bits);
取模
//v % (2^n)可以轉化為去掉n位之前的值
int mod = v & (2^n - 1);
乘2的n次方
int r = v << n;
除2的n次方
int r = v >> n;
除2的餘
int r = v & 1;
判斷語句 v == a ? b : a;
v = a ^ b ^ v;
否為2的冪
bool power2(int v){
return ((v & (v - 1)) == 0) && (v != 0);
}
求整數的平均值
//第1部分:計算相同位的平均值
//第2部分:計算不同位的平均值
int average(int x, int y){
return (x & y) + ((x ^ y) >> 1);
}
判斷兩數符號是否相反
bool f = ((a ^ b) < 0);
根據掩碼mask合併a和b, mask為1的位為b的值,反之為a的值
unsigned int r = a ^ ((a ^ b) & mask);
計算二進位制v中1的個數n
int count_1(int v) {
int n = 0;
while (v) {
n++;
v &= (v - 1);
}
return n;
}
計算二進位制v中0的個數n
int count_0(int v) {
int n = 0;
while (v + 1) {
n++;
v |= (v + 1);
}
return n;
}
下一個2的冪次方
unsigned int nextpowerof2(register unsigned int x) {
if (x == 0) {
return 1;
}
x--;
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return(x + 1);
}
上一個2的冪次方
unsigned int lastpowerof2(register unsigned int x) {
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return(x & ~(x >> 1));
}
計算二進位制數字前導0的個數
int clz(unsigned int x) {
if (x == 0) return 32;
int e = 31;
//1111 1111 1111 1111 0000 0000 0000 0000
if (x & 0xFFFF0000) { e -= 16; x >>= 16; }
//0000 0000 0000 0000 1111 1111 0000 0000
if (x & 0x0000FF00) { e -= 8; x >>= 8; }
//0000 0000 0000 0000 0000 0000 1111 0000
if (x & 0x000000F0) { e -= 4; x >>= 4; }
//0000 0000 0000 0000 0000 0000 0000 1100
if (x & 0x0000000C) { e -= 2; x >>= 2; }
//0000 0000 0000 0000 0000 0000 0000 0010
if (x & 0x00000002) { e -= 1; }
return e;
}
refer: