计算机中的二进制数有四种主要表示形式,那就是原码、反码、补码和移码,其中最重要的是前三种。

1. 原码

对于人脑来说,我们都知道,+表示正数,-表示负数,然而在计算机二进制中也引入这两个符号肯定是不行的,因为在计算机中只有0和1这两个字,根本不认识“+”和“-”这两个符号。计算机中的任何行为都依赖于它的物理结构。计算机是没有思维的,所以得让计算机在0和1之间识别出对应数的正与负。

     最开始的时候,人们约定在一个二进制数前用第一位(最高位)来表示符号,即1表示负,0表示正,这就是最初“原码”的概念。“原码”就是“原始码位”,或者“原始编码”的意思,就是对应二进制数本身所代表的形式。比如,+3(以8位字长为例,下同),符号位为0,3转化为二进制就是11,那么+3的原码就是00000011(最高位为符号位,正数的符号位为“0”,其余数值位不足部分补0)。同理, -3的符号位为1,3转化为二进制就是11,最终-3的原码就是10000011(不足8位时在前面用0补足)。在日常的书写中,原码的表示形式是用方括号下面加上一个“原”字下标来区别的,如[+3] 原= 00000011,[-3]原= 10000011。

   再来计算+127和-127各自的原码。+127中符号位为“0”,127的二进制为“1111111”,这样[+127]原=01111111;而-127中的符号位也为“1”,所以最终[-127]原=11111111。

     最应该注意的是,在原码表示形式中,0有“+0”和“-0”之分。对应的原码分别是0 0000000和1 0000000。

 

2.补码

原码的设计很不错,至少可以成功地区分出二进制数的正与负了,但是这种方法仍有一些局限性,那就是原码在加、减法运算中不方便,符号位需要单独处理、单独判断。同为正数的加、减是没什么问题的,可是异号相加、减时就存在问题了。如1-1,如果用原码计算的话结果为-2,显然不正确。

   (0 0000001)原 + (1 0000001)原 = (1 0000010)原 = -2

另外,在原码中0有+0和-0两种表示形式,这就存在二义性了,在计算机中是绝对不能容忍的。于是后来就想到一种能解决原码中存在的这些问题的另一种表示形式——补码。

 

补码的编码规则如下:正数的补码和原码相同;

负数的补码是通过先把除符号位外其他各位取反,再在末位(最低位)加1得到的。 负数求补规则:符号位不变,其余各位取反加1;

这样,我们只要让减数通过一个求反电路,再通过一个+1电路,然后再通过加法器就可以实现减法运算了。 这样在计算机中方便表示

 

经验之谈 如果要把一个补码转换成原码该如何操作呢?很简单,只需要把原码转换成补码的过程倒过来操作就行了。因为正数的补码与原码一样,所以正数补码的原码就是其补码,而负数补码的原码是先在最后一位加1,然后对其除符号位外的其他各位全部取反得到。只有相同码制的数才能进行操作,结果就是对应的码制,也就是原码数与码数的运算,结果也为原码,反码数与反码数的运算结果也为反码,补码数与补码数的运算结果也为补码。如果结果是负数,要判断结果是否正确,需要再将其对应的码制转换为原码。

 

补码首先继承了原码的特点(可以表示正与负),而且它包括了两个优点:

可以把符号位一起运算;

0只有一种表示形式,没有二义性。

下面同样以上面的1-1为例,如果采用补码形式,则算式如下:

(0 0000001)补 + (1 1111111)补 = 0 0000000 = 0

结果完全正确。其实这里涉及一个计算机运算中“模”的概念

我们把一个计量单位称为模或模数。例如,时钟是以十二进制进行计数循环的,即以12为模。在时钟上,时针加上(正拨)12的整数倍或减去(反拨)12的整数倍,时针的位置不变。例如,14点钟在舍去模12后,成为(下午)2点钟(14=14-12=2);从0点出发逆时针拨10格即减去10小时,也可看成从0点出发顺时针拨2格(加上2小时),即2点(0-10=-10=-10+12=2)。因此,在模12的前提下,-10可映射为+2。

由此可见,对于一个模数为12的循环系统来说,加2和减10的效果是一样的。所以,在以12为模的系统中,凡是减10的运算都可以用加2来代替,这样就把减法问题转化成加法问题了(注:计算机的硬件结构中只有加法器,所以大部分的运算都必须最终转换为加法)。10和2对模12而言互为补数。

同理,计算机的运算部件与寄存器都有一定字长的限制,因此它的运算也是一种模运算。如果字长为8,则当计数器计满8位也就是256个数后会产生溢出,又从头开始计数。产生溢出时的那个量就是计数器的模。显然,8位二进制数的模数为2的8次方,即256。在计算中,两个互补的数称为“补码”,这就是“补码”表示形式诞生的由来。

十进制数2-3=(0 0000010)补 +(1 1111101)补 =(11111111)补 = -1,也是正确的。十进制数123-121=(0 1111011)补+(1 0000111)补=(0 0000010)补= 2,也是正确的。

另外,在补码表示形式中,0仅有一种表示形式,因为无论是“+0”,还是“-0”的补码均为0 0000000。

2. 补码的加法运算

补码的加法运算法则如下:

ios二进制数字表示 二进制表达数字_反码

 

该式表明,两个有符号数相加的补码可以通过先分别对两个数求补码,然后相加得到。在采用补码形式表示时,进行加法运算时可以把符号位和数值位一起进行运算(若符号位有进位,则溢出不管),结果为两数之和的补码形式。

 

3.补码的减法运算

补码的减法运算法则如下:

ios二进制数字表示 二进制表达数字_ios二进制数字表示_02

 


该公式表明,求两个机器数的差值(如[X-Y]补)的补码,可以通过求被减数的补码(如[X]补)与减数的负值的补码([-Y]补)的和得到。

[-Y]补是对减数进行求负操作,求负的规则是全部位(含符号位)取反后再加1(实际上也是分别对符号位和真值位进行求反,因为正数与负数的符号也正好相反)。例如:已知[15]补= 00001111,则[-15]补=11110000+1=11110001。

现在假设X=+35,Y =+18,要求[X-Y]补(字长为8)。