位運算學習筆記

基本知識

1.按位與&:把參與運算的兩個數對應的二進制位相與,只有對應的二進制均爲1時,結果的對應位才爲1,不然爲0。如:9&5中9能夠寫成(00001001),5能夠寫成(00000101),那麼9&5的運算結果爲0000 0001,輸出結果是1。code

  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,輸出結果是12get

4.取反~:把運算數的各個二進制位按位求反。如:~9至關於~(0000 1001),運算結果爲1111 0110。it

5.左億<<:把「<<」左邊的運算數的各二進制位向左移若干位,「<<」右邊的數是指定移動的位數,高位丟棄,低位補0。 如 :a<<4指把a的各二進位向左移動4位,如a=00000011(十進制爲3),左移4位後爲00110000(十進制48)。class

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,只是爲了之後好找遍歷

相關文章
相關標籤/搜索