我对补码的最初的印象是大一的时候老师说按位取反再加一,却不知道为什么这样做,最近看了一下资料,总结一下我的理解吧。
一、计数系统
一个计数系统可以存多少容量状态的数,我叫它作为计数系统的Mod。一个计数系统不断地加一,那么它表示的数的状态也会周期性地变化,我叫这个周期的大小叫做Mod。
举个两个例子,1、一个包含两个bit的存储单位,它可以表示00,加一变成01,加一变成10,加一变成11,再加一又变成了00。即该计数系统的Mod为4。2、一个时钟显示十二个小时,时针旋转一周后回到原来的状态,即该系统的Mod为12。
由此,可以得到一个结论。这种周期性变化的计数系统,一个状态加减整数倍的Mod,其状态不会有不会发生变化。00加上4次之后还是00,12点时阵转两圈后还是12点。
二、变减为加
在计算机中使用加法器对数据进行计算,那么如何进行减法的运算呢?
设Mod=16
若a=3,b=-4,则a+b=a+b+Mod=-1+Mod=a+(Mod-4)=15(在计数系统中-1和15等价)
实际上Mod-4就是b的补数,所有的减法在计算机中都可以转化为加上减数的补数,对应计算机上的概念就是补码。
因此,计算机是使用补码(补数)进行计算。
三、约定的正负号
设现有一个4位的计数系统,那么我们可以知道该系统的Mod=16,即该系统一共可以表示16个状态。我也约定这个四位系统的0000状态为0,向前连续加十六得到0000本身,对应表示的数字如下:
1111 = 15 0000 = 0
1110 = 14 0001 = 1
1101 = 13 0010 = 2
1100 = 12 0011 = 3
1011 = 11 0100 = 4
1010 = 10 0101 = 5
1001 = 9 0110 = 6
1000 = 8 0111 = 7
如果这个计数系统是无符号位的,显然可以知道它表示的数据范围为:0~15
如果这个计数系统是有符号位的呢?
首先要对这些数据进行分配,现在的教科书上的做法就是把Mod前一半划分给0~7,后一半Mod划分给-8~-1,即如下图(这里二进制都是补码):
1111 = -1 0000 = 0
1110 = -2 0001 = 1
1101 = -3 0010 = 2
1100 = -4 0011 = 3
1011 = -5 0100 = 4
1010 = -6 0101 = 5
1001 = -7 0110 = 6
1000 = -8 0111 = 7
现在约定最高位为符号位,则显然正数的补码就是它本身,负数的补码和原码对照图如下:
1111 = -1 1001 -> 1110 +1 -> 1111
1110 = -2 1010 -> 1101 +1 -> 1110
1101 = -3 1011 -> 1100 +1 -> 1101
1100 = -4 1100 -> 1011 +1 -> 1100
1011 = -5 1101 -> 1010 +1 -> 1011
1010 = -6 1110 -> 1001 +1 -> 1010
1001 = -7 1111 -> 1000 +1 -> 1001
1000 = -8 1000 -> 1111 +1 -> 1000
这不正是按位取反再加一么。