2.1.4 定点数的编码表示

定/浮点表示解决了小数点的表示问题。但是,对于一个数值数据来说,还有正/负号的表示问题。计算机中只能表示0和1,因此,正/负号也用0和1表示。这种将数的符号用0和1表示的处理方式称为符号数字化。一般用0表示正号,用1表示负号。

数字化后的符号能否和数值部分一起参加运算呢?为解决该问题,就产生了多种把符号位和数值部分一起编码的方法。因为任意一个浮点数都可用一个定点小数和一个定点整数表示,所以,只需考虑定点数的编码表示,有原码表示法、补码表示法、反码表示法和移码表示法4种定点数编码表示方法。

通常将数值数据在计算机内部编码表示后的数称为机器数,而其值(即现实世界中带有正负号的数)称为机器数的真值。例如,-10(-1010B)用8位补码表示为1111 0110,说明机器数1111 0110B(F6H或0xF6)的真值是-10,或者说,-10的机器数是1111 0110B(F6H或0xF6)。根据定义可知,机器数一定是一个0/1序列,通常缩写成十六进制形式。

假设机器数X的真值XT的二进制形式(即式中为0或1)如下:

假设对XTn位二进制数编码后,机器数X表示如下:

X=Xn-1Xn-2X1X0

机器数Xn位,式中Xi为0或1,其中,第一位Xn-1是数的符号,后n-1位Xn-2X1X0是数值部分。数值数据在计算机内部的编码问题,实际上是机器数X的各位Xi的取值与真值XT的关系问题。

在上述对机器数X及其真值XT的假设条件下,下面介绍各种带符号定点数的编码表示。

1.原码表示法

一个数的原码表示由符号位直接跟数值位构成,因此,原码表示法也称符号-数值(sign and magnitude)表示法。原码表示法中,正数和负数的编码表示仅符号位不同,数值部分完全相同。

原码编码规则如下。

• 当XT为正数时,Xn-1=0,

• 当XT为负数时,Xn-1=1,

原码0有两种表示形式:[+0]=0 00…0,[-0]=1 00…0。

根据原码定义可知,对于数-10(-1010B),若用8位原码表示,则其机器数为1000 1010B(8AH或0x8A);对于数-0.625(-0.101B),若用8位原码小数表示,则其机器数为11010000B(D0H或0xD0)。

原码表示法的优点是,与真值的对应关系直观、方便;其缺点是,0的表示不唯一,给使用带来不便,并且原码运算中符号和数值部分必须分开处理。现代计算机中不用原码表示整数,只用原码小数表示浮点数的尾数部分。

2.补码表示法

补码表示法可实现加减运算的统一,即用加法实现减法运算。在计算机中,补码用来表示带符号整数。补码表示法也称2-补码(two's complement)表示法,由符号位后跟真值的模2n补码构成,因此,在介绍补码的概念之前,先介绍模运算的概念。

(1)模运算

在模运算系统中,若ABM满足关系A=B+K×MK为整数),则记为AB(mod M),即AB各除以M后的余数相同,故称BA为模M同余。在模运算系统中,一个数与它除以“模”后得到的余数等价。

钟表是一个典型的模运算系统,其模数为12。假定现在钟表时针指向10点,要将它拨向6点,则有以下两种拨法。

• 逆时针拨4格:10-4=6。

• 顺时针拨8格:10+8=18≡6(mod 12)。

因此在模12系统中,10-4 ≡ 10+(12-4)≡ 10+8(mod 12),即-4 ≡ 8(mod 12),称8是-4对模12的补码。同样有-3≡9(mod 12)、-5≡7(mod 12)等。

由上述例子与同余的概念,可得出如下结论:对于某一个确定的模,某个数A减去小于模的另一个数B,可用A加上-B的补码来代替。这是补码可借助加运算实现减运算的理论基础。

例2.9 假定在钟表上只能顺时针方向拨动时针,如何用顺拨的方式实现将指向10点的时针倒拨4格?拨动后钟表上是几点?

解:钟表是一个模运算系统,其模为12。根据上述结论,可得:

10-4≡10+(12-4)≡10+8≡6(mod 12)

因此,可从10点顺时针拨8(-4的补码)格来实现倒拨4格,最后是6点。

例2.10 假定算盘只有4档,且只能做加法,则如何用该算盘计算9828-1928的结果?

解:这个算盘是一个“4位十进制数”模运算系统,其模为104。根据上述结论,可得:

9828-1928≡9828+(104-1928)≡9828+8072≡7900(mod 104

因此,可用9828加8072(-1928的补码)来实现9828减1928的功能。

显然,在只有4档的算盘上运算时,若运算结果超过4位,则高位无法在算盘上表示,只能用低4位表示结果,留在算盘上的值相当于除以104后的余数。

推广到计算机内部,n位运算部件就相当于只有n档的二进制算盘,其模为2n

计算机中的存储、运算和传送部件位宽有限,相当于有限档数的算盘,因此计算机中所表示的机器数的位宽也有限。在两个n位二进制数的运算过程中,可能会产生一个多于n位的结果。此时,计算机和算盘一样,只能舍弃高位而保留低n位,这样做可能会产生以下两种结果。

• 剩下的低n位数不能正确表示运算结果,即舍弃的高位是运算结果的一部分。例如,在两个同号数相加时,相加得到的和超出n位数可表示的范围,称此时发生了溢出(overflow)现象。

• 剩下的低n位数能正确表示运算结果,即高位的舍弃并不影响其运算结果。在两个同号数相减或两个异号数相加时,运算结果就是这种情况。舍去高位的操作相当于“将一个多于n位的数除以2n,保留其余数作为结果”的操作,即“模运算”操作。如例2.10中最后相加的结果为17 900,但因为算盘只有4档,最高位的1自然被丢弃,得到正确的结果7900。

(2)补码的定义

根据上述同余的概念和数的互补关系,可引出补码的表示:正数的补码,符号为0,数值部分是它本身;负数的补码等于模与该负数绝对值之差。因此,数XT的补码可用如下公式表示:

• 当XT为正数时,[ XT]=XT=M+XT(mod M);

• 当XT为负数时,[ XT]=M-|XT|=M+XT(mod M)。

因此得到以下结论:对于任意一个数XT,[ XT]=M+XT(mod M)。

对于具有一位符号位和n-1位数值位的n位二进制整数的补码来说,其补码定义如下:

[XT]=2n +XT(-2n -1XT<2n -1,mod 2n

(3)特殊数据的补码表示

通过以下例子说明几个特殊数据的补码表示。

例2.11 分别求出补码位数为nn+1时-2n -1的补码表示。

解:当补码位数为n时,其模为2n ,因此

[-2n -1]=2n -2n -1=2n -1(mod 2n )=1 0…0(n-1个0)

当补码位数为n+1时,其模为2n +1,因此

[-2n -1]=2n +1-2n -1=2n +2n -1(mod 2n +1)=1 10…0(n-1个0)

从该例可知,同一个真值在不同位数的补码表示中,其对应的机器数不同。因此,在给定编码表示时,一定要明确编码的位数。在机器内部,编码的位数就是机器中运算部件的位数。

例2.12 设补码位数为n,求-1的补码表示。

解:对于整数补码有:[-1]=2n -1=11…1(n个1)。

对于n位补码表示来说,2n-1的补码为:

[2n -1]=2n +2n -1(mod 2n )=2n -1=1 0…0(n-1个0)

最高位为1,说明对应的真值是负数,与实际真值不符,显然n位补码无法表示2n-1。由此可知,在n位补码定义中,真值的取值范围包含-2n-1,但不包含2n-1

例2.13 求0的补码表示。

解:根据补码的定义,有:

[+0]=[-0]=2n ± 0=1 00…0(mod 2n )=0 0…0(n个0)

从上述结果可知,补码0的表示是唯一的。这带来了以下两个方面的好处:

• 减少了+0和-0之间的转换。

• 少占用一个编码表示,使补码比原码能多表示一个最小负数。在n位原码表示的定点数中,100…0用来表示-0,但在n位补码表示中,-0和+0都用00…0表示,因此,正如例2.11所示,100…0可用来表示最小负整数-2n-1

(4)补码与真值之间的转换

根据定义,求一个正数的补码时,只需将正号(+)转换为0,数值部分无须改变;求一个负数的补码时,需要做减法运算。

例2.14 设补码的位数为8,求110 1100和-110 1100的补码表示。

解:补码的位数为8,说明补码数值部分有7位,根据补码定义可得

[110 1100]=28+110 1100=100000000+110 1100(mod 28)=0110 1100

[-110 1100]=28-110 1100=100000000-110 1100

=10000000+10000000-110 1100

=10000000+(111 1111-110 1100)+1

=10000000+001 0011+1(mod 28)=1001 0100

本例中是两个绝对值相同、符号相反的数。其中,负数的补码计算过程中,第一个10000000用于产生最后的符号1,而第二个10000000被拆为111 1111 + 1,而(111 1111-110 1100)实际上是将数值部分110 1100各位取反。模仿这个计算过程,不难推导出负数补码计算的一般步骤:符号位为1,数值部分“各位取反,末位加1”。

因此,可用以下简单方法求一个数的补码:对于正数,符号位取0,其余位与真值相同;对于负数,符号位取1,其余各位由数值部分“各位取反,末位加1”得到。

例2.15 假定补码位数为8,用简便方法求X=-110 0011的补码表示。

解:[X]=1 001 1100+0000 0001=1 001 1101。

对于由负数补码求真值的简便方法,可通过以上由真值求负数补码的计算方法得到。对于符号位为1的补码,其真值的符号为负,数值部分先减1再取反。例如,对于例2.15中的补码表示1 001 1101,数值部分通过计算111 1111-(001 1101-1)得到,该计算可以变为(111 1111-001 1101)+1,即进行“取反加1”操作。因此,由补码求真值的简便方法如下:若符号位为0,则真值的符号为正,其数值部分不变;若符号位为1,则真值的符号为负,其数值部分的各位由补码“各位取反,末位加1”得到。

例2.16 已知[XT]=1 011 0100,求真值XT

解: X T=-(100 1011+1)=-100 1100。

根据上述有关补码和真值转换规则,不难发现,根据补码[XT]求[-XT]的方法如下:对[XT]“各位取反,末位加1”。这里要注意最小负数取负后会溢出。

例2.17 已知[XT]=1 011 0100,求[-XT]

解:[-XT]=0 100 1011+0000 0001=0 100 1100。

例2.18 已知[XT]=10000000,求[-XT]

解:[-XT]=0 111 1111+00000001=10000000(结果溢出)。

例2.18中出现了“两个正数相加,结果为负数”的情况,因此,结果与实际真值不符,称为结果溢出,该例中,8位整数补码1000 0000对应的是最小负数-27,对其取负后的值为27(即128),8位整数补码能表示的最大正数为27-1=127,显然128无法用8位补码表示,结果溢出。

(5)变形补码

为了便于判断运算结果是否溢出,某些计算机中采用一种双符号位的补码表示方式,称为变形补码,也称为模4补码。在双符号位中,左符是真正的符号位,右符用来判断溢出。

假定变形补码的位数为n+1(其中符号占2位,数值部分占n-1位),则变形补码表示如下:

[XT]变补=2n+1+XT(-2n-1XT<2n-1,mod 2n+1

例2.19 已知X T=-1011,分别求出变形补码取6位和8位时[XT]变补的编码

解:[XT]变补=26-1011=1000000-001011=110101。

[XT]变补=28-1011=100000000-00001011=11110101。

3.反码表示法

负数的补码可采用“各位取反,末位加1”的方法得到,若仅各位取反而末位不加1,则可得到负数的反码表示。

反码表示法存在以下不足:0的表示不唯一;表数范围比补码少一个最小负数;运算时必须考虑循环进位。因此,反码在计算机中很少使用,有时用作数码变换的中间表示形式。

4.移码表示法

浮点数用两个定点数表示,用定点小数表示浮点数尾数,用定点整数表示浮点数的阶(即指数)。一般情况下,浮点数的阶用一种称为移码的编码表示。阶的编码表示称为阶码

阶可能为正数或负数,进行浮点数加减运算时,必须先对阶(即比较两个数阶的大小并使之相等)。为简化对阶操作,使操作过程不涉及阶的符号,可对阶加上一个常数,该常数称为偏置常数(bias),使所有阶都转换为正整数,这样,在比较浮点数的阶时,就是比较两个正整数,因而可直观地从左到右按位对比两个数,从而简化对阶操作。

假设表示阶E的移码的位数为n,则[E]=偏置常数+E,通常,偏置常数取2n-1或2n-1-1。