Skip to content

利用ASCII码与位运算异或进行大小写转换

大小写字母在ASCII码中差32(1<<5)

c^=1<<5

计算数字中1的数量

int countOne(int n){
  int count = 0;
  while (n != 0){
    count++;
    n = (n-1) & n;// 去掉最右边一个1
  }
  return count;
}

不用临时变量交换值

numbers[0] ^= numbers[1];
numbers[1] ^= numbers[0];
numbers[0] ^= numbers[1];

最后一个1

num&-num

去掉最右边一个1

n &= n - 1

最低位 0 改 1

n |= n + 1

把右边连续的1变成0

x & (x+1)

把末k位变成1

x | ((1 << k)-1)

末k位取反

x ^ ( 1 << k - 1 )

绝对值

(n ^ (n >> 31)) - (n >> 31)
n>0 则 n >> 31 = 0 ,即为 n^0-0
n<0 则 n >> 31 = -1 ,即为 n^-1 + 1 同 ~n+1 ,即补码

符号

(n >> 31) | (~((~n + 1) >> 31) + 1)

(~n + 1) >> 31  					正数为 -1 ,负数为 0。
~((~n + 1) >> 31) 				取反后正数为 0 ,负数为 -1
(~((~n + 1) >> 31) + 1)		加一后正数为 1 ,负数为 0
(n >> 31) |								正数为 0,负数为 -1 和上一步进行或运算。则正数为 1,负数为 -1

取最大值

int max(int a, int b){
    return (b & ((a - b) >> 31)) | (a & (~(a - b) >> 31));
}

枚举集合

# 设集合为 s,从大到小枚举 s 的所有非空子集 sub
for (int sub = s; sub > 0; sub = (sub - 1) & s) {
    // 处理 sub 的逻辑
}

# 设元素范围从 0 到 n−1,从空集枚举到全集 
for (int s = 0; s < (1 << n); s++) {
    // 处理 s 的逻辑
}

Gosper's Hack

枚举在最大 n 个bit位 ,中有 k 个bit为 1 的所有数

int subset = (1 << k) - 1;
while (subset < (1 << n)) {
    // do something
    int lb = subset & -subset;
    int x = subset + lb;
    subset = ((subset ^ x) / lb >> 2) | x;
}