- 计算机系统:基于x86+Linux平台
- 袁春风 朱光辉 余子濠编著
- 4192字
- 2024-08-06 16:54:07
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)如下:
假设对XT用n位二进制数编码后,机器数X表示如下:
X=Xn-1Xn-2…X1X0
机器数X有n位,式中Xi为0或1,其中,第一位Xn-1是数的符号,后n-1位Xn-2…X1X0是数值部分。数值数据在计算机内部的编码问题,实际上是机器数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)模运算
在模运算系统中,若A、B、M满足关系A=B+K×M(K为整数),则记为A≡B(mod M),即A、B各除以M后的余数相同,故称B和A为模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 -1≤XT<2n -1,mod 2n )
(3)特殊数据的补码表示
通过以下例子说明几个特殊数据的补码表示。
例2.11 分别求出补码位数为n和n+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-1≤XT<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。