1.4 计算机中的数制和编码基础
计算机的工作过程就是对数据进行处理。计算机是一个典型的数字化设备,它只能识别0和1,所有的计算机都是以二进制数的形式进行算术运算和逻辑操作的。
1.4.1 计算机中的数制及转换
1.计算机中的数制
计算机最早是作为一种计算工具出现的,所以最基本的功能是对数进行加工和处理。数在机器中是以器件的物理状态来表示的。一个具有两种不同的稳定状态且能相互转换的器件可以用来表示1位(bit)二进制数。二进制数有运算简单、便于物理实现、节省设备等优点,所以目前在计算机中的数几乎全部采用二进制表示。但是二进制数书写起来太长,且不便于阅读和记忆,又加上目前大部分微型计算机是8位、16位或32位的,都是4的整数倍,而4位二进制数即是1位十六进制数,所以微型计算机中的二进制数都采用十六进制数来表示,日常生活中我们主要使用十进制数。因此在使用微型计算机时常用的计数制有二进制数、十六进制数、十进制数3种。
(1)十进制数(Decimal)
以10为基数的计数制称为十进制计数制。十进制数有如下两个特点:
① 有0~9共10个不同的数码。
② 在加法中采用逢10进1的原则。
人们在实际生活中常用的是十进制数。
(2)二进制数(Binary)
以2为基数的计数制称为二进制计数制。二进制数有如下两个特点:
① 有0、1共2个不同的数码。
② 在加法中采用逢2进1的原则。
计算机中使用的是二进制数。
(3)十六进制数(Hexadecimal)
十六进制是人们学习和研究计算机中二进制数的一种工具,它是随着计算机的发展而广泛应用的。十六进制数有如下三个特点:
① 有0~9、A、B、C、D、E、F共16个不同的数码。
② 在加法中采用逢16进1的原则。
③ 在书写一个十六进制数时,如果该数据的高位为A~F,则在高位的前面加“0”,如0AH、0EFH、0FEABH、0CB98H等。
十进制数、二进制数和十六进制数之间的关系如表1-4所示。
表1-4 十进制、二进制数及十六进制数对照表
为了区别十进制数、二进制数及十六进制数三种数制,可以在数的后面加1个字母。规定B(binary)表示二进制数,D(decimal)表示十进制数,H(hexadecimal)表示十六进制数,其中十进制数后面的字母D可以省略。
2.各种数制之间的转换
人们习惯的是十进制,计算机采用的是二进制,而二进制的表示多采用十六进制,因此必须掌握数制的转换问题。
(1)二进制数和十六进制数间的相互转换
根据表1-4所示的对应关系即可实现它们之间的转换。
二进制整数转换为十六进制数,其方法是从右(最低位)向左将二进制数分组:每4位为1组,最后一组若不足4位则在其左边添加0,每组用1位十六进制数表示。如:
1111111000111B=1FC7H
十六进制数转换为二进制数,只需用4位二进制数代替1位十六进制数即可。如:
3AB9H=0011101010111001B
(2)十六进制数和十进制数间的相互转换
十六进制数转换为十进制数十分简单,只需将十六进制数按权展开即可。如:
十进制整数转换为十六进制数可用除16取余数法,即用16不断地去除待转换的十进制数,直到商等于零为止。将所得的各次余数,依倒序排列,即可得到所转换的十六进制数。例如,将38947转换为十六进制数,即38947=9823H。其方法及算式如图1-15所示。
图1-15 将38947转换为十六进制数
一个十进制小数转换成十六进制小数时,可采用乘16取整的方法进行。例如,将十进制数0.7875转换为十六进制数,转换结果为0.7875D=0.C99H。其方法和算式如图1-16所示。
图1-16 将0.7875转换为十六进制数
注意小数转换不一定能算尽,只需算到一定精度的位数即可,因此可能会产生一些误差,但当位数较多时,这个误差就很小了。
如果一个十进制数既有整数部分又有小数部分,可将整数部分和小数部分分别进行十六进制数的等值转换,然后合并即可得到结果。
1.4.2 带符号数的表示
1.机器数与真值
计算机在处理实际问题时所遇到的数据通常是带符号数。在计算机中,对于带符号数来说,一般用最高位表示数的正、负。对于正数,最高位规定为“0”,对于负数,最高位规定为“1”,例如:
56H可以表示01010110B(对于8位二进制数来说,D7位表示数的正负,D6~D0表示数的绝对值),-56H可以表示11010110B。
0256H可以表示0000 001001010110B(对于16位二进制数来说,D15位表示数的正负,D14~D0表示数的绝对值),-0256H可以表示1000 001001010110B。
在计算机中,用二进制数表示有符号数,用最高位表示符号,其余的为数值位,这样一组连同符号也编码化的二进制数称为机器数,机器数所代表的数值大小称为机器数的真值。
【例1-2】 写出X1=+42,X2=-42,X3=+91,X4=-91的真值和机器数。
设机器的字长为8位,则有:
[X1]真=+101010B=+42,X1的机器数为00101010B。
[X2]真=-101010B=-42,X2的机器数为10101010B。
[X3]真=+1011011B=+91,X3的机器数为01011011B。
[X4]真=-1011011B=-91,X4的机器数为11011011B。
2.机器数的原码、反码、补码
数据在计算机内采用符号数字化处理后,机器可表示并识别带符号的数据。为了改进运算方法、简化控制电路,人们研究出多种有符号数的编码形式,最常用的有三种方法,即原码、反码、补码表示法。
数X的原码记为[X]原,反码记为[X]反,补码记为[X]补。
(1)原码表示法
对于带符号数来说,用最高位表示数的正负,其余各位表示数的绝对值,这种表示方法称为原码表示法,即仅将符号位数字化表示为0或1,数的绝对值与符号一起编码,或者称为“符号-绝对值”的编码。
原码表示的特点如下:
① 最高位为符号位,正数为0,负数为1。
② 8位二进制原码表示数的范围是-127~+127,十六位二进制原码表示数的范围是-32767~+32767。
③ 0的原码有两种表示方法,即+0和-0,设字长为8位:
[+0]原=00000000B
[-0]原=10000000B
采用原码表示时,编码简单直观,但也带来一些麻烦,一是引起机器中“零”的表示不唯一,零有二义性,给机器判零带来麻烦,必须在设计时约定好机器采用正零或负零;二是不便于进行加减运算。用原码进行四则运算时,符号位需单独处理,而且原码加减运算规则复杂。例如对有符号数的加法规则为:若两个数同号,两数绝对值相加,结果冠以共同的符号;若两个数异号,两数绝对值相减,结果冠以绝对值大的数值的符号。而减法又有一套规则。故原码表示法一般不用于加减运算。
(2)反码表示法
正数的反码与原码相同,如[56H]反=[56H]原=01010110B。
负数的反码等于原码除符号位外,其余各位按位取反。因此,求-56H反码的过程如下:
对应正数56H的原码为0101 0110B;按位求反后为1010 1001B,即-56H的反码为10101001B。
反码的特点:
① 反码表示法中,最高位仍为符号位,正数为0,负数为1。
② “0”有两种表示方法:当字长是8位时,[+0]反=00000000B,[-0]反=11111111B。
③ 8位二进制反码表示数的范围是-127~+127,16位二进制反码表示数的范围是-32767~+32767。
④ 正数的反码与原码相同,负数的反码符号位为1,其数值部分按位取反。
(3)补码
在计算机内,带符号数并不是用反码表示的,而是用补码表示的,引入“原码”、“反码”的目的只是为了方便理解“补码”的概念而已。
不用原码表示的原因是:用原码表示时,“0”的原码并不唯一,0的原码可以表示为00000000B(即+0),也可以表示为10000000B(即-0),这会造成混乱;再就是用原码表示时,减法并不能转化为加法运算,反码也存在类似的问题。在计算机中,带符号数用补码表示后,减法可以转化为加法运算,例如:
① 100H是8位二进制能表示的最大数,加上100H后,对计算结果没有影响,原因是8位二进制无法存放100H中的“1”,即D8位。
② 由于8位二进制不能存放D8位,结果133H中最高位“1”自然丢失。
显然,56H-23H的结果与56H+0DDH的结果相同,即引入补码后,减法可以用加法来完成。可见,在8位二进制中,23H与0DDH互为补码。
下面以钟表为例进一步理解补码的问题。对一个现实生活中的钟表来说,现在时钟指在11时,需要调校到6时,则可以顺时针拨11+7=12+6=6;也可以逆时针拨11-5=6。这里,自动丢失的循环最大值(12)称为模,即当模是12时,11-5=12+7=6,其中7称为-5的补码,即
(-5)补=12-|-5|=7
依次类推,对于n位(如8位)二进制而言,其模为2n(28),则(负数)补=2n-|负数|。
补码的定义如下:
正数的补码与反码、原码相同;负数的补码等于它的反码加1。
例如,+23H的补码:00100011B;-23H的补码:-23的原码为10100011B,-23H的反码为11011100B;反码加1后为11011101B,即-23H的补码为11011101B(相当于无符号数的0DDH)。
可见,用补码表示时,若最高位为0,表示该数为正数,数值部分就是真值;若最高位为1,则表示该数为负数,数值部分并不是它的真值,必须再求补后,才得到该数的绝对值,如上例中的-23H的补码为11011101B,按位取反后为00100010B,加1后为00100011B,即23H。
补码的特点:
① 补码表示中,最高位仍为符号位,正数为0,负数为1。
② 0仅有一种表示方法,即[+0]补=[-0]补。
③ 8位二进制补码表示数的范围是-128~+127,16位二进制补码表示数的范围是-32768~+32767;对于同一个数,作为8位二进制数的补码和作为16位二进制数的补码不同,这一点要特别注意。
注意:对于8位二进制数10000000B,若为补码表示为[-128]补,若为原码表示[-0]原,若为反码表示为[-127]反。
关于补码,注意以下几点:
① 在微型计算机中所有带符号的数都是用补码表示的。一个数据是带符号的数还是不带符号的数,事先是已知的。
② 当求补码的真值时,例如8位的补码,若最高位为0时,其余7位即为此数的二进制数值。但当最高位为1(即负数)时,需要把其余7位求反以后最低位加1,才是它的二进制数的绝对值。例如:
[X]补=10010100B
[X]真=-(1101011)=-1101100B=-108D
③ 采用补码的目的在于可用加法运算代替减法运算,从而可以简化硬件结构,降低成本。
【例1-3】 计算64-10=?
【解】
64-10=54,可用[X]补=[64]补-[+10]补进行减法运算。而[64]补=01000000B,[+10]补=00001010B。运算如图1-17所示。
图1-17 补码相减算式
该运算也可写成下式:
64-10=64+(-10)=54
可用[X]补=[64]补+[-10]补进行加法运算。其中[-10] 补=11110110B,运算如图1-18所示。
图1-18 补码相加算式
故[X]补=00110110B。由以上运算可知,补码相加的结果与补码相减的结果是一致的。因此,可用补码相加代替补码相减的运算。
④ 补码运算时符号位不需要单独处理,符号位与数值部分一起参加运算,在不发生溢出的情况下,运算结果(包括符号位)是正确的。
8位二进制数用来表示有符号数、原码、反码和补码,如表1-5所示。
表1-5 原码、反码和补码表
从表1-5 可以看出,8位二进制数,无符号数表示范围是0~255,有符号数原码表示范围中-127~+127,反码表示范围是-127~+127,补码表示范围是-128~+127。
3.带符号数溢出及其判断方法
(1)什么是溢出
在选定了运算字长和数的表示方法之后,如果运算的结果超出了计算机所能表示的数据范围,则称这种情况为广义上的溢出。
从严格意义上讲,广义上的溢出既包括带符号数的溢出,也包括无符号数的溢出,但下面把带符号数的数据结果超出表示范围称为溢出,而把无符号数的数据结果超出表示范围称为进位。因为对于无符号数的加减运算,无论运算的结果是否超出数据表示范围(在计算机字长范围内),运算结果都是正确的。而对于带符号数的加减运算,如果没有溢出,则运算结果是正确的,而如果产生溢出,则运算结果是错误的。
对于8位字长的微处理器,其原码、反码和补码表示的范围分别为
原码 -127~+127(0FFH~7FH)
反码 -127~+127(80H~7FH)
补码 -128~+127(80H~7FH)
当8位带符号数的运算结果超过以上范围时,就会产生溢出。
对于16位字长的微处理器,其原码、反码和补码表示的范围分别为
原码 -32767~+32767(0FFFFH~7FFFH)
反码 -32767~+32767(8000H~7FFFH)
补码 -32768~+32767(8000H~7FFFH)
当16位带符号数的运算结果超过以上范围时,就会产生溢出。
【例1-4】 已知X=01000000B,Y=01000001B,进行补码的加法运算。
【解】
[X]补=01000000B=+64
[Y]补=01000001B=+65
[X]补+ [Y]补=10000001B=-127
两个正数相加,其结果应该是+129,但运算结果为-127,这显然是错误的,其原因在于和数+129 > +127,超出了8位补码所能表示的最大值,使数值部分占据了符号位的位置,产生了溢出错误。
(2)判断溢出的方法
溢出只能出现在两个同符号数相加或两个异符号数相减的情况下。利用双进位方法判断有无溢出是一种常用的方法,其规则如下:在两个同符号数相加或两个异符号数相减时,如果次高位向最高位有进位(或借位),而最高位向前无进位(或借位),则结果发生溢出;反之,如果次高位向最高位无进位(或借位),而最高位向前有进位(或借位),则结果也发生溢出。
这种方法是利用最高位和次高位的进位/借位状态进行“异或”来判断的。对8位二进制数来说,如果溢出记为OF,最高位和次高位的进位/借位状态分别记为C7和C6,则OF=C7⊕C6,当OF=1时表示有溢出,当OF=0时表示无溢出。
在微机中,可用多字节表示更大的数,避免产生溢出错误。
1.4.3 定点数和浮点数
计算机中运算的数有整数,也有小数。通常有两种规定:一种是规定小数点的位置固定不变,这时的机器数称为定点数;另一种是小数点的位置可以浮动,这时的机器数称为浮点数。微型计算机中常使用定点数。
1.定点数
所谓定点法,是指小数点在数中的位置是固定不变的,以定点法表示的实数称为定点数。根据小数点位置的固定方法不同,又可分为定点整数和定点小数表示法。前面介绍的整数均为定点整数,可以认为小数点固定在数的最低位之后。
如果小数点隐含固定在整个数值的最右端,符号位右边所有的位数表示的是一个整数,即为定点整数。例如,对于16位机,如果符号位占一位,数值部分占15位,于是机器数0111111111111111 的等效十进制数为+32767,其符号位、数值部分、小数点的位置示意如图1-19所示。
图1-19 定点整数的符号位、数值部分和小数点位置示意图
如果小数点隐含固定在数值的某一位置上,即为定点小数。
如果小数点固定在符号位之后,即为纯小数。假设机器字长为16位,符号位占一位,数值部分占15位,于是机器数1000000000000001的等效十进制数为-2-15,其符号位、数值部分、小数点的位置示意图如图1-20所示。
图1-20 纯小数的符号位、数值部分和小数点位置示意图
2.浮点数
所谓浮点数,是指计算机中数的小数点位置不是固定的,或者说是“浮动”的。在计算机中,浮点数法一般用来表示实数,可以采用“阶码表示法”来表示浮点数,它由整数部分和小数部分组成,一个实数可以表示成一个纯小数和一个乘幂之积。
采用浮点数最大的特点是,比定点数表示的范围大。
例如,对于十进制数56.725=102×0.56725;对于二进制数110.11=22×1.1011。
对于任何一个二进制数N,都可以表示为
N=(2±E)×(±S)
浮点数在计算机中的编码基本格式如图1-21所示。
图1-21 浮点数在计算机中的编码基本格式
其中,E称为阶码,阶码为0表示E为正,为1表示E为负。由此可见,小数点的实际位置随着阶码E的大小和符号而浮动决定;±S为全部有效数据,称为尾数部分。
例如,1001.011=20100×(0.1001011)。此处,0100部分称为阶码且为正,(0.1001011)部分称为尾数。
浮点数的格式多种多样。例如,某计算机用4个字节表示浮点数,阶码部分为8位补码定点整数,尾数部分为24位补码定点小数,如图1-22所示。
图1-22 4个字节表示的浮点数
【例1-5】 描述用4个字节存放十进制浮点数“136.5”的浮点格式。
【解】 由于(136.5)10=(10001000.1)2,将二进制数“10001000.1”进行规格化,即
10001000.1=0.100010001×28
阶码28表示阶符为“+”,阶码为“8”的二进制数为“0001000”;尾数中的数符为“+”。小数值为“100010001”。
十进制小数“136.5”在计算机中的表示如图1-23所示。
图1-23 规格化后的浮点数
在实际应用时,由于阶码指数可使用不同的编码(原码、补码等),尾数的格式和小数点的位置也可以有不同的规定,所以浮点数的表示方法不唯一,不同的计算机可以有不同的规定。
1.4.4 计算机中常用的编码
计算机除了用于数值计算外,还要进行大量的文字信息处理,也就是要对表达各种文字信息的符号进行加工。例如计算机和外设如键盘、(字符)显示器、打印机之间的通信都采用字符方式输入/输出。目前计算机中最常用的两种编码是美国信息交换标准代码(ASCII码)和二-十进制编码(BCD码)。
1.美国信息交换标准代码(ASCII码)
ASCII(American Standard Code for Information-Interchange)码是美国信息交换标准代码的简称,主要给西文字符进行编码。它采用7位二进制数表示一个字符,包括32 个标点符号,10个阿拉伯数字,52个英文大小写字母,34个控制符号,共128个。编码与字符之间的对应关系如附录A所示。
在计算机系统中,存储单元的长度通常为8位二进制数(即一个字节),为了存取方便,规定一个存储单元存放一个ASCⅡ码,其中低7位表示字母本身的编码,第8位(即bit7)用做奇偶校验位或规定为零(通常如此)。因此,也可以认为ASCII码的长度为8位。
奇偶校验的主要目的是用于在数据传输过程中,检测接收方的数据是否正确。收发双方预约为何种校验,接收方收到数据后检验1的个数,判断是否与预约的校验相符,倘若不符,则说明传输出错,可请求重新发送。奇校验时,bit7的取值应使得8位ASCII码中1的个数为奇数;偶校验时,bit7的取值应使得ASCII码中1的个数是偶数。例如:
“8”的奇校验ASCII码为00111000B,偶校验ASCII码为10111000B。
“B”的奇校验ASCII码为11000010B,偶校验ASCII码为01000010B。
2.BCD码(二进制编码的十进制数)
十进制毕竟是人们最习惯的计数方式,在向计算机输入数据时,常用十进制数输入,但计算机只识别二进制数,因此每1位十进制必须用二进制数表示。1位十进制数包含0~9十个数码,必须用4位二进制数表示,这样就需要确定0~9与4位二进制数0000B~1111B之间的对应关系,其中较常用的8421BCD码规定了十进制数0~9与4位二进制数编码之间的对应关系,见表1-6。
表1-6 十进制数与4位二进制数编码之间的对应关系
注:在BCD码中,不使用1010B(0AH)~1111B(0FH)。
例如,4567.89的BCD码为0100010101100111.10001001(每1位十进位数用相应的4位二进制数表示即可)。BCD码的一个优点就是10个BCD码组合格式容易记忆。一旦熟悉了4位二进制数的表示,对BCD码就可以像十进制数一样迅速自如地读出。同样,也可以很快地得出以BCD码表示的十进制数。例如,将1 个BCD数转换成相应的十进制数:
(011101101001.100100110101)BCD=769.935
BCD码采用4位编码,4位一组表示1位十进制数,分别表示十进制数的个位、十位、百位等,低4位对高4位的进位为“逢十进一”。它不是二进制数,而是按4位二进制数的展开值和按4位一组解释为十进制数。BCD码和二进制数之间的转换不能直接实现,二进制数转换为BCD码时,必须先将其转换为十进制数。例如,要将二进制数1101.1B转换为BCD码,首先需要将二进制数按权展开,转换为十进制数,再转换为BCD码:
1101.1B=1×23+1×22+0×21+1×20+1×2-1=13.5
13.5=(00010011.0101)BCD
同样,要将BCD码转换为二进制数,首先要把BCD码转换为十进制数,然后再转换为二进制数。
BCD编码可以简化人机关系,但它比纯二进制编码的效率低。对同一个给定的十进制数,用BCD编码表示的位数比用纯二进制表示的位数要多。而每位数都需要某些数字电路与之对应,这就使得与BCD码连接的附加电路成本提高,设备的复杂性增加,功耗较大。用BCD码进行运算所花的时间比用纯二进制码进行运算所花的时间要多,而且复杂。
计算机中存储BCD码的形式有两种:压缩BCD码和非压缩BCD码。
(1)压缩BCD码
压缩BCD码用4位二进制数表示1位十进制数,一个字节可以表示2位十进制数。例如10010111B表示十进制数97。
(2)非压缩BCD码
非压缩BCD码用8位二进制数表示1位十进制数,高4位总为0000,低4位的0000~1001表示0~9。例如00001001B表示十进制数9。
尽管BCD码比较直观,但BCD码与二进制数之间的转换并不方便,需要转换成十进数后,才能转换为二进制数,反之亦然。
前面介绍了在使用计算机时二进制数、十进制数、十六进制数、ASCII码、BCD码以及带符号数的表示等问题,这里要注意微型计算机能处理的数据只有二进制数,计算机并不认识什么正数、负数、BCD码、ASCII码等,计算机中数的表现形式只有二进制数,其他的数制和性质需要人们来进行分析与说明。如在某存储器中存放一个二进制数11111111B(0FFH),这个数多大?这要看人们如何看了,如果是一个无符号数,就是255;如果是一个有符号数,就是-1;如果是个BCD码,就是一个无效的数;如果是个ASCII码,就代表“DEL”键的ASCII码值。