位运算学习笔记

基本知识

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

原文地址:https://www.cnblogs.com/pyyyyyy/p/10858153.html