各种位运算的常见用法
1. and(与)运算
一个数 and 1的结果就是取二进制的最末位,可用于判断奇偶性
2. or(或)运算
一个数 or 1的结果就是把二进制末尾变成1,若想把一个数二进制末尾变成0,则先 or 1再减一就可以了,即变为最接近的偶数。
3. xor(异或)运算
异或可以这样定义:0和1异或0都不变,异或1则取反。异或的逆运算是其本身,即(a xor b) xor b = a。
定义两个符号#和@(我怎么找不到那个圈里有个叉的字符),这两个符号互为逆运算,也就是说(x # y) @ y = x
x <- x # y
y <- x @ y
x <- x @ y
执行了第一句后x变成了x # y。那么第二句实质就是y <- x # y @ y,由于#和@互为逆运算,那么此时的y变成了原来的x。第三句中x实际上被赋值为(x # y) @ x,如果#运算具有交换律,那么赋值后x就变成最初的y了。这三句话的结果是,x和y的位置互换了。
由此我们可以写出这样的两值交换的代码
x ^= y ^= x ^= y;
接下来列出常用的变换操作
功能 | 位运算 | 示例 |
---|---|---|
把最后一位变成1 | x | 1 | 101100->101101 |
把最后一位变成0 | x | 1 - 1 | 101101->101100 |
最后一位取反 | x ^ 1 | 101101->101100 |
把右数第k位变成1 | x | (1 << (k - 1)) | 101001->101101, k=3 |
把右数第k位变成0 | x & ~ (1 << (k - 1)) | 101101->101001, k=3 |
右数第k位取反 | x ^ (1 << (k - 1)) | 101001->101101, k=3 |
取末三位 | x & 7 | 1101101->101 |
取末k位 | x & (1 << k - 1) | 1101101->1101, k=5 |
取右数第k位 | x >> (k - 1) & 1 | 1101101->1, k=4 |
把末k位变成1 | x | (1 << k - 1) | 101001->101111, k=4 |
末k位取反 | x ^ (1 << k - 1) | 101001->100110, k=4 |
把右边连续的1变成0 | x & (x + 1) | 100101111->100100000 |
把右起第一个0变成1 | x | (x + 1) | 100101111->100111111 |
把右边连续的0变成1 | x | (x - 1) | 11011000->11011111 |
取右边连续的1 | x ^ (x + 1) >> 1 | 100101111->1111 |
去掉右起第一个1的左边 | x & (x ^ (x - 1)) | 100101000->1000 |
最后一个再树状数组中会用到。
转载地址: http://www.matrix67.com/blog/archives/263