位运算是我们在编程中常会遇到的操作,但仍然有很多开发者并不了解位运算,这就导致在遇到位运算时会“打退堂鼓”。实际上,位运算并没有那么复杂,只要我们了解其运算基础和运算符的运算规则,就能够掌握位运算的知识。接下来,我们一起学习位运算的相关知识
程序中的数在计算机内存中都是以二进制的形式存在的,位运算就是直接对整数在内存中对应的二进制位进行操作。
位运算的基础
我们常用的 3, 5 等数字是十进制表示,而位运算的基础是二进制。即人类采用十进制,机器采用的是二进制,要深入了解位运算,就需要了解十进制和二进制的转换方法和对应关系。
二进制
十进制转二进制时,采用“除 2 取余,逆序排列”法:
用 2 整除十进制数,得到商和余数;
再用 2 整除商,得到新的商和余数;
重复第 1 和第 2 步,直到商为 0;
将先得到的余数作为二进制数的高位,后得到的余数作为二进制数的低位,依次排序;
排序结果就是该十进制数的二进制表示。例如十进制数 101 转换为二进制数的计算过程如下:
逆序排列即二进制中的从高位到低位排序,得到 7 位二进制数为 1100101,如果要转换为 8 位二进制数,就需要在最高位补 0。即十进制数的 8 位二进制数为 01100101。
其完整过程如下图所示:
有网友整理了常见的进制与 ASCII 码对照表,表内容如下:
ASCII 控制字符
ASCII 可显示字符
补码
现在,我们已经了解到二进制与十进制的换算方法,并拥有了进制对照表。但在开始学习位运算符之前,我们还需要了解补码的知识。
数值有正负之分,那么仅有 0 和 1 的二进制如何表示正负呢?
人们设定,二进制中最高位为 0 代表正,为 1 则代表负。例如 0000 1100 对应的十进制为 12,而 1000 1100 对应的十进制为 -12。这种表示被称作原码。但新的问题出现了,原本二进制的最高位始终为 0,为了表示正负又多出了 1,在执行运算时就会出错。举个例子,1 + (-2) 的二进制运算如下:
这显然是有问题的,问题就处在这个代表正负的最高位。接着,人们又弄出了反码(二进制各位置的 0 与 1 互换,例如 0000 1100 的反码为 1111 0011)。此时,运算就会变成这样:
这次好像正确了。但它仍然有例外,我们来看一下 1 + (-1):
零是没有正负之分的,为了解决这个问题,就搞出了补码的概念。补码是为了让负数变成能够加的正数,所以 负数的补码= 负数的绝对值取反 + 1,例如 -1 的补码为:
-1 补码推导的完整过程如下图所示:
反过来,由补码推导原码的过程为 原码 = 补码 - 1,再求反。要注意的是,反码过