1.4 原码、反码和补码
在十进制数中,有符号数用符号“+”表示正数,符号“−”表示负数。在计算机系统中,有符号数可分为符号位和数值位两部分。有符号数的最高位作为符号位,用0表示“+”,用1表示“−”,其余为数值位部分。
1.4.1 机器数和真值
在计算机系统中,把由符号位和数值位构成的一个数称作为机器数,而数值位部分称为机器数的真值。
例如,X1=+0101011 B,机器数为00101011 B,真值为0101011 B;X2=−0101011 B,机器数为10101011 B,真值为0101011 B。
1.4.2 原码
原码是计算机对有符号数采用二进制表示的一种方法,由符号位和数值位组成。原码的最高位作为符号位,0表示正数,1表示负数。数值位表示数值绝对值的大小,绝对值的编码规则与前面讲的无符号数编码规则相同。常见的8位有符号数的数值范围是−127~+127, 16位有符号数的数值范围−32767~+32767。如果运算结果超出可表示的有符号数的范围时,就会发生溢出,使计算结果出错。
例如,X1=+1001010B,X2=−1001010B,则X1原码是[X1]原=01001010 B,X2对应的原码是[X2]原=11001010 B。
在原码表示方法中,0有两种不同的值,即[+0]原=00000000 B,[−0]原=10000000 B。
1.4.3 反码
反码也是计算机对有符号数采用二进制表示的一种方法,符号位与原码的符号位表示方法一样,对于正数,符号位为0;对于负数,符号位为1。反码的数值部分则不同,其值变化与它的符号位有关。对于正数,反码的数值部分和原码数值部分相同;对于负数,反码的数值部分是原码的数值部分按位取反(即1变0,0变1)。
例如:X1=+ 0000111 B,[X1]反= 0 0000111 B,X2=−0000111 B,[X2]反= 1 1111000 B。
由于0的原码有两种不同的值,因此0的反码也有两种不同的值,即[+0]反=00000000, [−0]反=11111111。
1.4.4 补码
二进制数的算术运算包含加、减、乘、除四种运算,计算机在执行乘法和除法运算时,实际上都是通过做加减法运算来实现的。当设计做减法运算的电路时,必须先比较两个数绝对值的大小,再将绝对值大的数减去绝对值小的数,最后在相减的结果前面加上绝对值较大的数的符号。减法运算逻辑电路复杂,运算速度也比做加法运算慢得多。
为了能使加、减法运算统一用加法运算来实现,人们通过补码来表示有符号数值。补码的引入使得两个数无论相加还是相减,均可通过加法运算来实现。因此,计算机中一切有符号数都是以补码的形式参与算术运算的。
补码也是一种二进制数码,又称为“对2的补数”,其表示方法与该数是正数还是负数有关。正数的补码与该数的原码和反码是一样的,对于负数,求补码的方法是:符号位不变,数值部分按位对原码取反,然后在最低位加1,通常简称为“取反加1”。
例如,X1=+ 0000111 B,[X1]补= 0 0000111 B;X2=−0000111 B,[X2]补= 1 1111001 B。
在补码表示法中,[+0]补=0 0000000B,[−0]补=[−0]反+1=1 1111111+1=1 00000000B,舍弃进位后,[−0]补=0 0000000B。由此可见,0具有唯一的补码[0]补=0 0000000B。
【例1.4.1】 求二进制数X1= +0001011B和X2= −0001011B对应的原码、反码和补码。
解:对于原码、反码和补码来说,最高位都是符号位,其他位则与数值部分有关。如果该数为正数,则对应的原码、反码和补码按位相同。如果该数为负数,则反码是原码的按位取反,补码则是原码的按位取反加1。
因此,二进制数+0001011B和−0001011B所对应的原码、反码和补码分别表示如下:
[X1]原 =00001011B, [X1]反 =00001011B, [X1]补 =00001011B。
[X2]原 =10001011B, [X2]反 =11110100B, [X2]补 =111101011B。
1.4.5 有符号数的加减运算
通过采用补码来表示有符号数,可以把两个数的加、减法运算统一为加法运算,即把减法运算通过用[A]补+[−B]补的方法实现,因此机器在进行运算时符号位一律按加法参与运算。如果计算的结果产生了进位,则把进位丢弃,保留符号位和数值位即可。
【例1.4.2】 计算X1=36+45,X2=36−45和X3=−36−45的结果。
解:对于有符号数的算术运算,采取补码进行,因此先算出各个数的补码,再按补码运算方法进行计算。
(1)X1=36+45
由结果可知,[X1]补=01010001B是正数,因此[X1]原= [X1]补=01010001B,对应的十进制数为X1=81。
(2)X2=36−45
由结果可知,[X2]补=11110111B是负数,因此对其进行求补运算得到原码X2:
[X2]原={[X2]补}反+1=10001000+1=10001001,对应的十进制数为X2=−9。
(3)X3=−36−45
由结果可知,舍弃进位后,[X3]补=10101111B 是负数,因此对其进行求补运算得到原码X3:[X3]原= {[X3]补}反+1=11010000+1=11010001B,对应的十进制数为X3=−81。
采用补码表示的符号数经过运算后得到的结果仍然是补码的形式,并非该数值的原码。如果运算结果的符号位为0,则代表结果是正数,而正数的原码和补码是相同的。如果运算结果的符号位为1,则代表结果是负数,而负数的补码与原码不同,因此需要对运算结果进行一次求补运算才能得到该数值对应的原码。
注意:当两个同符号数采用补码进行相加运算时,它们的绝对值之和不能超过有效数值位所能表示的最大值,否则会产生溢出,得到错误的计算结果。