位取反运算符
位取反运算符(~)是对所有位的数字取反操作

位与运算符
位与运算符( & )可以对两个数的比特位进行合并。它会返回一个新的数,只有当这两 个数都是 1 的时候才能返回 1 。

位或运算符
位或运算符( | )可以对两个比特位进行比较,然后返回一个新的数,只要两个操作位任 意一个为 1 时,那么对应的位数就为 1 。

位异或运算符
位异或运算符,或者说“互斥或”( ^ )可以对两个数的比特位进行比较。它返回一个 新的数,当两个操作数的对应位不相同时,该数的对应位就为 1 。

左移运算符和右移运算符
- 位左移运算符(<<)和位右移运算符(>>)可以把所有位数的数字向左或向右移动一 个确定的位数。
- 位左移和右移具有给整数乘以或除以二的效果。将一个数左移一位相当于把这个数翻 倍,将一个数右移一位相当于把这个数减半。
无符号整数的移位操作
- 已经存在的比特位按指定的位数进行左移和右移
- 任何移动超出整型存储边界的位都会被丢弃
- 用 0 来填充向左或向右移动后产生的空白位

有符号整数的移位操作
- 有符号整数使用它的第一位(所谓的符号位)来表示这个整数是正数还是负数。符号位为 0 表示为正 数,1 表示为负数。
- 其余的位数(所谓的数值位)存储了实际的值。有符号正整数和无符号数的存储方式是一样的,都是 从 0 开始算起。
- 但是负数的存储方式略有不同。它存储的是 2 的 n 次方减去它的绝对值,这里的 n 为数值位的位 数。

补码表示的优点
- 首先,如果想给-4加个-1,只需要将这两个数的全部八个比特位相加(包括符号 位),并且将计算结果中超出的部分丢弃。

- 其次,使用二进制补码可以使负数的位左移和右移操作得到跟正数同样的效果,即每向左移一位就将自身的数值乘以2,每向右移一位就将自身的数值除以2。要达到此目的,对有符号整数的右移有一个额外的规则:当对正整数进行位右移操作时,遵循与无符号整数相同的规则,但是对于移位产生的空白位使用符号位进行填充,而不是 0 。

位运算符经典算法
两个数字交换
- 不借助临时变量,交换两个变量的值。

求无符号整数二进制中 1 的个数
-
给定一个无符号整型(UInt)变量,求其二进制表示中 “1” 的个数,要求算法的执行 效率尽可能的高。
-
思路:看一个八位整数 10 100 001 ,先判断最后一位是否为 1 ,而“与”操作可以达 到目的。可以把这个八位的数字与 00000001 进行“与”操作。如果结果为 1 ,则表示 当前八位数的最后一位为 1 ,否则为 0 。怎么判断第二位呢?向右移位,再延续前面的 判断即可。

-
如果整数的二进制中有较多的 0 ,那么我们每一次右移一位做判断会很浪费,怎么改进 前面的算法呢?有没有办法让算法的复杂度只与“1”的个数有关?
-
思路:为了简化这个问题,我们考虑只有高位有 1 的情况。例如:11 000 000 ,如何跳过前面低 位的 6 个 0 ,而直接判断第七位的 1 ?我们可以设计 11 000 000 和 10 111 111(也就是 11 000 000 - 1)做“与”操作,消去最低位的 1 。如果得到的结果为 0,说明我们已经找到消去里面最后一个1。如果不为0,那么说明我们消去了最低位的1,但是二进制中还有其他的1,我们的计数器需要加 1 ,然后继续上面的操作。

引申:如何判断一个整数位为 2 的整数次幂
- 给定一个无符号整型(UInt)变量,判断是否为 2 的整数次幂。
- 思路:一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是 1 ,而其 它所有位都是 0 。根据前面的分析,把这个整数减去 1 后再和它自己做与运算,这个整数中唯一的1就变成0了,也就是得到的结尾为 0 。
