1.2 计算机中数值数据信息的表示
1.2.1 机器数和真值
计算机在本质上只能识别0、1表示的二进制数码。为了表示正数和负数,专门选择一位二进制数来表示数的符号,该位为0,表示正号;该位为1,表示负号,通常选择最高位作为符号位。
这就是说,数的符号在计算机中也数值化了。一个数在机器(计算机)中的表示形式称为机器数,而数本身的实际值叫做真值(机器数真值)。真值可以用二进制数表示,也可用十进制数表示,但根据习惯,常用十进制数表示,如图1-1所示。
图1-1 机器数真值
机器数有如下特点:
(1)机器数的正、负号是数值化的。
(2)机器数所能表示的数的范围受到机器(计算机)字长的限制。
那么什么是计算机字长呢?我们先来解释几个计算机中的常用术语。
① 位(bit):是计算机所能表示的最小数据单位,它只有两种状态0和1。要想表示更大的数,就得把更多的位组合起来作为一个整体,每增加一位,所能表示的数就增大一倍。
② 字节(Byte):一个8位二进制数称为1字节,它是计算机处理数据的基本单位(B)。在计算机中,其存储器容量大小常以字节数的多少来度量。常用的4种度量单位是KB、MB、GB和TB,其大小分别为:
1KB=210B=1024B
1MB=210×210B=1024KB
1GB=210×210×210B=1024MB
1TB=210×210×210×210B=1024GB
③ 字(Word):作为单位一般指16位二进制数,但也把计算机处理数据时,处理器通过数据总线一次存取、加工和传送的数据位数称为字,这时字通常由1字节或若干字节组成。
④ 字长(Word Length):指处理器的二进制位数。8位微处理器的字长为8位;16位微处理器的字由2字节构成;32位微处理器的字则由4字节构成。字长是衡量计算机性能的一个重要标志,字长越长,性能越强,精度越高。
(3)小数点不能直接标出,需要按一定方式约定小数点的位置。
需要说明的是,在计算机系统开发和应用中会涉及二进制(Binary,简写B)、八进制(Octal,O或Q)、十进制(Decimal,D)和十六进制(Hexdecimal,H)等数制,其中十六进制最常用、最方便,它与二进制的关系简明、直接,并用0~9,A~F(H)代表0~15(D)。
1.2.2 数的表示方法——原码、反码和补码
为妥善解决符号数值化的表示与运算问题,设定了机器数x的三种不同编码形式,即原码、反码和补码。分别记作[x]原、[x]反和[x]补。
1.原码
设x=x1x2…xn-1,其中xi为一位二进制数,i=1,2,…,(n-1)。n位二进制数
一个数的原码,就是数值部分为绝对值,加上用0和1分别表示数的符号+和-的机器数。
【例1-1】 x1=67=+1000011,[x1]原=01000011;x2=-67=-1000011,[x2]原=11000011。
在原码表示法中,根据定义,数0的原码有两种不同形式(设字长为8位):
[+0]原=00000000,[-0]原=10000000
原码表示简单易懂,而且与真值的转换方便。但原码表示的数不便于计算机运算,因为在两原码数运算时,首先要判断它们的符号,然后再决定用加法还是用减法,导致机器的结构相应地复杂化或增加机器的运算时间。为解决上述问题,引入反码和补码表示法。
2.反码
设x=x1x2…xn-1,其中xi为一位二进制数,i=1,2,…,(n-1)。定义
式中,
根据定义,正数的反码与原码相同;对于负数,反码的符号位为1,其余位为数值位按位取反。
【例1-2】 x1=83=+1010011,[x1]反=01010011;x2=-83=-1010011,[x2]反=10101100。
在反码表示法中,根据定义,数0的反码也有两种不同形式(设字长为8位):
[+0]反=00000000,[-0]反=11111111
3.补码
引入补码的概念,一方面是为了解决原码、反码存在的一些问题,另一方面是为了将计算机中的加、减运算简化为单纯的加法运算,这种运算上的特性与补码本身的定义有关。
(1)同余的概念和补码
设有两个数a=17,b=27,若用10去除a和b,则它们的余数均为7,我们称17和27在以10为模时是同余的,并记作17=27 (mod 10)。
或者说,17和27在以10为模时是相等的。此处的模是一个计量系统所能表示的最大量程(或一个计量单位称为模或模数)。
由同余概念,不难得出
a+M=a (mod M),a+2M=a (mod M)
因此当a为负数时,如a =-4,在以10为模时,有
-4+10=-4 (mod 10) 即 6=-4 (mod 10)
上式说明,在以10为模时,-4与+6是相等的。我们称+6为-4的补码,或者说+6与-4对模10来说互为补数。有了补码的概念,就可将减法转化为加法(加补码)来进行。如:
7-4=7+6 (mod 10)
该式说明,在以10为模时,7减4可以通过7加-4的补码6来进行,而所得结果是相同的(只要在加补码6时,将所产生的进位舍弃即可,这正是以10为模的意思)。
现在把同余和补码的概念推广到二进制数。设计算机字长为n位,那么其模为2n,即
这就是说,字长n位的机器,2n在机器中仅能以n个0表示。或者说,2n和0在机器中表示的形式是一样的。
(2)补码求法
设x=x1x2…xn-1,其中xi为一位二进制数,i=1,2,…,(n-1)。定义
或写成
① 正数的补码。[x]补=[x]原=[x]反 。
【例1-3】 [+127]原=[+127]反=[+127]补=
② 负数的补码。先求负数的反码,然后在反码最低一位上加1就得到该负数的补码。
还可以用形式上更简便的方法求得负数x的补码:符号位为1,将原数值中最右边一个1及其后面的0保持不变,而最右一个1以左的各位按位取反。
【例1-4】 x1=-0011000,[x1]补=11101000;x2=-1000000,[x2]补=11000000。
根据定义,数0的补码仅有一种形式:[+0]补=[-0]补=
若已知一个负数的补码,再取一次补,则 {[x]补}补=[x]原。
【例1-5】 设[x]补=10010111,求x的真值。
所以,[x]原=11101001,x=-1101001=-105。
当已知8位二进数补码符号位为1时,表示该数为负数。此时要注意,其余几位不是该二进制的数值,一定要把它们按位取反,且在最低位加1,才是该二进制数的值(真值)。
十进制数及其对应的8位二进制数的原码、反码和补码表示如表1-1所示。
表1-1 十进制数及其对应的8位二进制数的表示方法
小结:
(1)有符号数三种编码的最高位都是符号位。符号位为0,表示真值为正数,其余位为真值;符号位为1,表示真值为负数,其余位除原码外,不再是真值。对于反码,只需按位取反,便是真值;对于补码,还需按位取反加1,才是真值。
(2)对正数,三种编码是一样的,即[x]原=[x]反=[x]补。对于负数,三种编码就不同了。所以说,原码、反码和补码的实质是用来解决负数在机器中的表示而引入的编码方法。
(3)8位二进制数原码、反码和补码所能表示的数值范围不完全相同。它们分别是-127~+127,-127~+127和-128~+127。其中对0的表示也不尽相同,原码和反码有两种表示方法,补码只有一种表示方法。
(4)当计算机采用不同的码制时,运算器和控制器的结构将不同。采用原码形式的计算机称原码机。类似地,有反码机和补码机。小型计算机和微型计算机大多为补码机(实际上原码机与反码机已不采用了)。
1.2.3 补码的运算
从以上讨论可知,在微型计算机中,有符号数以补码的形式在机器中存在和运算。这主要是因为补码的加、减运算比原码简单;符号位与数值位一起参加运算,并能自动获得正确结果。
设x和y是两个正数,可以证明,两个数和的补码等于两个数补码的和:
[x+y]补=2n+(x+y)=(2n+x)+(2n+y)=[x]补+[y]补
同样也可以证明,该两数差的补码等于被减数的补码与减数负值的补码(或称求补)之和。
[x-y]补=2n+(x-y)=2n+x+2n+(-y)=[x]补+[-y]补
上式说明,在补码运算中,两数差的运算可简化为单纯的加法运算。
x的补码直接由补码定义可得到,而[-y]补可通过对[y]补“连同符号位在内一起变反加1”得到(称为“求补”)。
【例1-6】 [y]补=00000100,[-y]补=11111100。
【例1-7】 计算x-y。x,y均为正数,且x>y。设x=122,y=37,字长n=8。
解:
求得真值为正数(01010101)2=85。
【例1-8】 计算x-y。x,y均为正数,且x<y。设x=64,y=65,字长n=8。
解:
求真值:(11111111)补={(11111111)补}补=- (00000001)=-1。
【例1-9】 计算x+y。x,y均为正数。设x=64,y=65,字长n=8。
解:
此时,两个正数相加得出负数,显然是错误的。这种情况称为“溢出”。由表1-1知,8位计算机中,由于最高位为符号位,剩下的数值位只有7位,表示数的范围是-128~+127。当两个正数相加其和大于127或两个负数相减其绝对值之和大于128时,就产生了“溢出”,致使结果出错。推广到字长n位的符号数,最高位为符号位,n-1位表示数值。能表示的最大值为2n-1-1(即n-1个1)。当运算结果超过此值,就会产生“溢出”。
小结:
(1)补码运算时,参加运算的两个数均为补码,结果也是补码,需转换才能得到真值。
(2)可以将减法变为加法运算,以简化硬件设计。
(3)运算时:① 符号位与数值位一起参加运算;② 符号位产生的进位可舍弃;③ 要保证运算结果不超过补码所能表示的数的最大范围,否则将产生“溢出”错误。为此,在计算机中设有专门电路用以判断运算结果是否产生溢出,并设置溢出标志告知本次运算的结果的状态。
(4)无符号数和有符号数的加法运算可用同一电路完成。
1.2.4 定点数与浮点数
在计算机中,不仅要处理整数运算,而且也要处理小数运算,如何处理小数点位置是十分重要的,通常用定点法和浮点法来表示小数点的位置。
(1)定点表示法。就是小数点位置在数中固定不变。例如:
1.100101,0.100101,110.0101
一般来说,小数点位置固定在哪个位置上并无限制,但为了使用简便,在计算机中有两种常用的定点数。
① 定点纯小数。把小数点固定在最高数值位左边,在小数点左边设有一位符号位,小数点本身不占位,其格式为:
② 定点纯整数。把小数点固定在最低数值位右边,最高位仍为符号位,小数点本身不占位,其格式为:
定点数的这两种表示法,在计算机中均有采用。但对一台机器而言,采用哪种方法,需事先约定。
【例1-10】 有如下两个8位二进制数:
【例1-11】 有例1-10中同样两个数,但小数点位置不同,则有
从上面两个例子可以看出,定点整数和定点小数在格式上毫无差别,这是因为定点数的小数点是隐含的,但它们的真值却不相同。此外,相同位数、不同码制的定点数表示的数的范围也不相同。
同一台计算机可处理的整数类型往往有很多种,以目前广泛使用的Pentium机为例,除了无符号整数之外,它还有三种不同类型的整数,如表1-2所示。
表1-2 Pentium处理器的三种整数类型
由于定点数是将小数点的位置固定,因此运算起来很不方便。一方面,它要求对所有原始数据要用比例因子化成小数或整数,算出结果又要用比例因子折算成真值;另一方面,这种方法所表示的数的范围小、精度低。所以有必要引入另一表示方法——浮点表示法。
(2)浮点表示法。为了在位数有限的前提下,尽量扩大数的表示范围,同时又保持数的有效精度,计算机往往采用浮点数表示数值。在浮点表示初期,把一个数通过改变小数点位置表示成2的p次幂和绝对值小于1的数S相乘的形式:
式中,N称为浮点数或实数;S是N的尾数,它是数值的有效数字部分,通常用带符号的定点小数表示,一般用原码表示;2是N的底数,是该进位计数制的基数,在计算机中不出现,是隐含的;p是指数,称为阶码,通常为带符号整数,一般用补码表示。阶码p的大小决定了数的范围,尾数S的长短则规定了数的有效数字的位数(精度)。在计算机中,p和S均为二进制数。
【例1-12】 试将以下数表示成浮点数形式。
1011.1101B=(0.10111101B)×24 =(0.10111101)×2100B
0.00101101B=(0.101101B)×2-2 =(0.101101)×2-10B
-111001010B=(-0.111001010B)×29 =(-0.111001010)×21001B
浮点数在机器中的一种表示形式如下:
也就是说,若要在机器中表示一个浮点数,阶码和尾数要分别表示,且都有自己的符号位。
通常,用一位二进制数pf表示阶码的符号位。当pf=0时,表示阶码为正;当pf =1时,表示阶码为负。同样,用一位二进制数Sf表示尾数的符号位。当Sf =0时,尾数为正;当Sf =1时,尾数为负。
若浮点数中1/2≤S<1,则称该浮点数为规格化了的浮点数。
【例1-13】 (-18.75)10=(-10010.11)2=(-0.1001011)×2+101。
假定尾数用8位二进制数表示,阶码用4位二进制数表示,且均含符号位,尾数用原码表示,则有
或表示成(1.1001011)×(10)0101。
【例1-14】 (0.078125)10=(0.000101)2=(0.101)×2-11。
同上例
阶码用补码表示,尾数用原码表示。
或表示成(0.1010000)×(10)1101。
最后介绍浮点数表示数的范围,若浮点数采用下列格式:
则浮点数表示数的范围是。
由于指数可以选用不同的编码(原码、补码等),尾数的格式和小数点位置也可以有不同规定,因此浮点数的表示方法不是唯一的。不同计算机有不同的规定,这就引起了相互间数据格式的不兼容性。为此,美国电气与电子工程师协会(IEEE)制定了有关的工业标准,已被众多计算机制造厂商所采用。
浮点数的长度可以是32位、64位甚至更长,位数越多,可表示的数的范围越大,精度也越高。
以当今流行的Pentium处理器中的浮点数为例。Pentium处理器中的浮点数格式完全符合IEEE标准,它表示成如下形式:
式中,(-1)Sf是该数的符号位,Sf=0或1,0表示正,1表示负;p是指数,它是一个带偏移量的整数,表示成无符号整数;(b0.b1b2b3…bS-1)是尾数,其中bi=0或1;S是尾数的长度,它表示尾数共S位。
表1-3为Pentium处理器中三种不同类型浮点数的格式。
表1-3 Pentium处理器中三种不同类型浮点数的格式
Pentium处理器浮点数的尾数最高位b0总是1,且和小数点一样隐含,在机器中并不明确表示出来。
【例1-15】 将十进制数178.125表示成单精度浮点数。
首先,将十进制数178.125表示成二进制实数:(178.125)10=(10110010.001)2。
然后,再将二进制实数表示成规格化形式: 10110010.001=1.0110010001×27。
因为指数等于7,加上偏移量127之后,p=7+127=134=(10000110)2。
因此,178.125的单精度浮点数表示为:
【例1-16】 单精度浮点数001111110 10110000000000000000000的十进制数值是多少?
先计算指数。因为 p=(01111110)2=(126)10,所以,指数=126-127=-1。
再计算尾数。规格化的尾数是 +1.1011。
所以该浮点数的数值为 +1.1011×2-1=+0.11011=(+0.84375)10。
【例1-17】 下面4个等式中,等号左面是二进制实数,等号右面是其等值的单精度浮点数表示。
0.11010001×210110=0 10010100 10100010000000000000000
-0.11010001×210110=1 10010100 10100010000000000000000
0.11010001×2-10010=0 01101100 10100010000000000000000
-0.11010001×2-10010=1 01101100 10100010000000000000000
需要指出的是,任意位精度浮点数可由定点处理器计算生成,而上文所述的属于机器精度浮点数,其精度由特定格式规定,后者的应用更为广泛。
相对于整数(定点数)的表示形式,浮点表示法所表示的数据范围大、精度高,但同时增加了运算的复杂度和时间开销。因而众多计算机系统中都将浮点运算集成为单独硬件部件——浮点运算单元(FPU,Floating-Point Unit),以增强浮点处理的能力。Intel公司在1980年发布了8087数学协处理器(浮点运算器件),该协处理器主要负责浮点运算,其数据类型为IEEE标准的格式。8087只能与8086/8088配合使用,将浮点运算结果传输给CPU。此后,Intel公司还相继推出了80287和80387协处理器。1989年发布的Intel 486DX中,已经将浮点运算部件做在CPU内部,而不再是作为一个选件。而其他的主流微处理器,如Motorola的68040和PowerPC也均把浮点运算部件集成在了内部。
1.2.5 BCD码及其十进制调整
由于二进制数具有很多优点,所以到目前为止在计算机内部多采用二进制运算。但是,二进制数书写起来很长,读起来也不方便。考虑到人们习惯,通常,数在送入机器之前,仍采用十进制编码,运算结果也以十进制数输出。这就要求在输入时将十进制数转换成二进制数,输出时将二进制数转换成十进制数,这项工作一般由机器自动完成。因而产生了一种适合于十进制数的二进制代码的特殊形式,即用4位二进代码来表示一位十进制数,简称BCD(Binary Coded Decimal)码。
要表示一个十进制数码,至少需要4位二进制数组合,其编码的选择有很多种方法,其中常用的BCD码如表1-4所示。而最常用的是用0~9各数字所对应的二进制数作为代码,称为8421 BCD(简称NBCD)码。
表1-4 常用BCD码编码表
从表1-4可见,8421码与十进制数的对应关系最直观,转换也十分简单,只需将十进制数的各位数字用与其对应的一组4位二进制数代替即可。下文所述的BCD码仅指8421BCD码。
【例1-18】 将十进制数83.6转换成BCD码。
(83.6)10=(1000 0011.0110)BCD
【例1-19】 将BCD码1001 0111.0100 0010转换成十进制数。
(1001 0111.0100 0010)BCD=(97.42)10
要注意,BCD码与真正的纯二进制数是不同的。它貌似二进制数,实为十进制数。通常用在计算的输入/输出设备中,作为计算机中二进制数与人们日常用的十进制数之间的一种过渡性编码,以简化人机关系。
由于BCD码只是将每个十进制数用4位二进制数来表示,而每组4位二进制数之间仍然是逢十进一的关系。因此,如果将这种BCD码直接交由计算机去运算,由于计算机总是将其作为二进制数来处理,结果可能会出错。
【例1-20】 求BCD码的7+6=?
1101为非法BCD码,运算结果出错,7+6的正确BCD码应为(00010011)BCD。
为了得到正确的BCD码的运算结果,必须对二进制数的运算结果进行调整,使之符合十进制数的运算和进位规律。这种调整称为十进制调整,其规则如下:
(1)若两个BCD数相加的结果大于9(1001),则应作“加6(0110)修正”。
(2)若两个BCD数相加的结果在本位上并不大于9(1001),但却产生了进位,相当于十进制数运算大于等于16,则也应“加6(0110)修正”。
【例1-21】 求BCD码54+48=?
低4位之和为1100,应作加6修正,修正后高4位又为1010,还应再作一次加6修正。故最终结果为102。
这里需要说明一点:实际上,在计算机中有十进制调整指令DAA(DAS),无论对加法或减法,机器能按照规则自动进行调整(加法时,“加6修正”;减法时,“减6修正”)。
BCD码在计算机中有两种表示方法,一种是用1字节表示两位十进制数,称为压缩BCD,如(56)10=(01010110)BCD;另一种称作非压缩BCD,它用8位二进制数表示一位十进制数,如(56)10=(0000010100000110)BCD。前者占内存少,利用率高;后者占内存多,但其运算及调整相对简单,在某些场合下使用。