请稍候,加载中....

二进制补充知识

大家可能已经了解到计算机内部信息通过1与0存储,如果计算机想存储一个2,那么在计算机内部存储的是10, 如果存储的是4,那么计算机内部存储的是1000,如果大家理解到这里,那只能说理解了一半。为什么说是一半呢,因为这个只是一个十进制正整数转换为二进制的一个结果,但是实际上,还有负数,浮点数、定点小数的存储,他们的存储并不是简单的直接转换为二进制保存。

这就是二进制的原码、补码、反码

二进制原码

要了解二进制原码,首先从他的符号位开始

符号位

在计算机中参与运算的数分为有符号数与无符号数

  • 无符号的数,也就是他的二进制信息里面不包含符号位,所以无符号数只能表示非负数
  • 有符号位的数,二进制的左边第一位为符号位,当这一位为0表示正数,为1表示负数

想一下,十进制的2与-2的二进制表示应该怎么样?

如果用8位二进制表示

2的二进制 - 0000 0010, 最左侧为0,表示这是一个正数

-2的二进制 - 1000 0010, 最左侧为1, 表示这是一个负数

那么这里的 0000 0010就称为十进制2的原码,同理 1000 0010就是十进制的-2的原码

原码的问题

根据数学运算规则,正数+他的负数应该等于0,比如2 + (-2) = 0, 那么我们来观察一下原码的运算:

0000 0010 + 1000 0010 = 1000 0100  对应十进制的 -4 ,这个结果显然不对

因此我们不能直接的在计算机中使用负数的原码来保存负数

二进制补码

既然原码不符合正负相加为0的运算法则,那么我们可以考虑一下,负数应该怎么样才能为0

还是以2的八位二进制为例

0的八位二进制为 0000 0000

那么 0000 0010 + ? = 0000 0000 ,?应该是个什么数。

如果我们直接考虑结果为 0000  0000,可能不好推算,但是如果假设可以添加1位,也就是 1 0000 0000, 能不能想到呢?

显然,可以考虑到 0000 0010 + 1111 1110 = 1 0000 0000, 最左侧的1由于超出了八位会被计算机丢弃,所以就可以得到0000 0000。

这里的 1111 1110就是 0000 0010的补码,是-2在计算机中的二进制存储

对于正数2,他的原码就是他的补码

二进制反码

正数的补码就是他的原码,这个比较好计算,那么负数的补码如何通过他的原码来计算出来?

这就需要用到反码

计算反码

反码就是将原来的二进制除符号位以外的位进行逐位取反

分析一下:

1000 0010  求他的反码

1111   1101  这个就是他的反码

这里大家考虑一下, 2的原码 + (-2的反码)的结果是什么?

0000 0010 + 1111 1101 = 1111 1111

可以看到反码相加的结果比目标0少了一个1,所以接下来就是很简单的结果

根据反码计算补码

只要在反码的基础上加上1,就得到了负数的补码

1111 1101 + 1 = 1111 1110

这样就计算出了他的补码

注意事项

在计算机中,无论正负数都是以补码形式存储,正数的补码就是他的原码,那么在进行位计算的时候,我们一定要记得使用补码进行位计算

以下面的运算为例:

# ~按位取反
print(~10)
# -11
print(~-10)
# 9

大家可以手工推算一下,是不是与运行结果一致

~10的计算过程:
以8位二进制表示, 按位取反是对补码取反
第一步:
10的补码是 0000 1010 

第二步:
由0000 1010按位取反可以得到:
1111 0101, 这得到是一个补码,从第一位可以看出是一个负数,所以需要根据这个补码计算他的原码,要计算原码首先计算他的反码

第三步:
计算反码
1111 0101 - 1 = 1111 0100 这就是他的反码(反码+1 = 补码)

第四步:
由反码计算他的原码:

1111 0100 -> 1000 1011  ,符号位保持不变,其他位取反,所以最后得到的是-11
 

~-10的计算过程:

第一步:

-10的原码是:

1000 1010, 这是负数的原码,~取反运算是在负数的补码上计算的,所以需要先计算出他的补码

第二步:

1000 1010 的补码是 1111 0110

第三步:

对 1111 0110进行取反得到 : 0000 1001,第一位是0,是一个正数,所以这个码就是原码,可以知道结果是9

 

 


Python学习手册-