计算机是用电来存储数据的,电路中的元件只有两种状态,有电和没电,所以计算机使用二进制存储数据很方便,高电平(有电)代表1,低电平(没电)代表0,这样只需要存储一串电信号就可以存储一个二进制数了。

正整数 1 的二进制表示是:

0000 0001

在计算机的电路中其实是7个低电平,和一个高电平。

用二进制数存储正数没有问题,但是负数如何存储呢?如何用0或1表示“负号”?

最简单的办法是取最高位当作符号位,最高位为0代表正数,最高位为1代表负数。

来看下面这两个数:

0000 0011
1000 0001

第一个数最高位是0,所以是正数,后面的二进制数为3,所以这个二进制数代表正数3.
第二个数最高位是1,所以这是个负数,后面二进制数为1,所以这个二进制数代表-1.

看似很完美吧,等一下,我们来计算一下 -1 + 1 的值:

1000 0001
0000 0001
---------
1000 0010

换算成整数是多少,-2。这和正常的逻辑,-1+1=0相差甚远。

从这里我们可以看出,仅取一个符号位代表负数是不行的,那么,怎样表示负数能让-1 + 1 = 0成立呢?

1xxx xxxx
0000 0001
---------
0000 0000

也就是说上式中的x是啥?

这还不简单,全是1呗!

1111 1111       //-1
0000 0001       //1
----------
0000 0000      //发生进位,最高位1被舍弃,最后结果为0

好了,到这里我们知道了,-1的二进制表示为1111 1111,那有什么规律吗,到底怎么算才能获得到一个数的二进制表示呢?

假如有一个数x:

0100 1011

把数x按位取反得到~x:

1011 0100

我们看到第一位为1,所以这应该是个负数,我们先不管这个数是多少,将x与~x相加:

 x: 0100 1011
~x: 1011 0100
-------------
-1: 111111111

结果是1111 1111,上面我们已经知道了二进制1111 1111代表-1,所以有:

x + (~x) = -1

那么,数x的负数表示-x就为:

-x = (~x) + 1

所以计算机中一个数的负数表示是先将这个数按位取反,然后加一

负数的这种表示方法叫做补码

第一次学习补码,可能会有点疑惑,用这么奇怪的方式计算出来的补码代表负数,会不会出现什么乱子?

其实只要保证,一个负数仅对应一个补码,并且一个补码也仅对应一个负数,就可以保证在计算中不会出现混乱,而按照补码的生成方式,这是可以保证的。而补码参与运算能够得出正确的结果,这就可以了,管它奇不奇怪呢。

最后推荐一个知乎的回答计算机补码运算背后的数学原理是什么?,里面对补码的设计理念写的很清楚。

posted @ 2019-08-30 14:29:07
评论加载中...

发表评论