位運算學習筆記


基本知識

1.按位與&:把參與運算的兩個數對應的二進制位相與,只有對應的二進制均為1時,結果的對應位才為1,否則為0。如:9&5中9可以寫成(00001001),5可以寫成(00000101),那么9&5的運算結果為0000 0001,輸出結果是1。

  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,只是為了以后好找


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM