1.5 计算机中的数与编码
计算机内部信息分为两大类:控制信息和数据信息。控制信息用于指挥计算机如何操作;数据信息是计算机操作的对象,它既可以用于表示数量的大小,也可以表示字符、汉字等。对于计算机而言,不论是控制命令还是数据信息,都要用“0”和“1”两个基本符号编码来表示。这种方式叫作二进制表示法。
在日常生活中人们最熟悉、使用最多的是十进制,数字用“0,1,…,9”10个符号表示,基于计算机本身的硬件结构,计算机中多采用二进制来表示和存储数据,但直接使用二进制数,由于位数较长,书写、阅读和记忆都不方便,因此,在计算机语言表达上,常采用十六进制,而计算机与人的信息交换又多用十进制。为了区分不同的进制,一般在数字后面加上数制字符,例如,2代表二进制,10代表十进制,16代表十六进制;也可以用字母来表示数制,B(Binary)代表二进制,D(Decimal)代表十进制,H(Hexadecimal)代表十六进制。
1.5.1 计算机中的数制
1.二进制数的表示法
二进制计数法的特点如下。
1)需要2个数字符号:0,1。
2)以2为底,逢2进位。
二进制数用尾缀B作为标识符。
二进制只有两个数码,即0和1,在电子计算机中容易实现。例如,用“1”表示高电平,用“0”表示低电平;还可表示脉冲的正负极等。二进制编码、加减运算规则简单。此外,二进制码的两个符号“1”和“0”还与逻辑数据“真”和“假”相对应,为逻辑运行带来了方便。
所有二进制数表示的大小都可以按“权”展开:
(NUM)B=kn-1×2n-1+kn-2×2n-2+…+k1×21+k0×20+k-1×2-1+…+k-m×2-m
其中,2n(如22、21、20、2-1、2-2)称为二进制数各数位的“权”。
【例1.1】1001.011B=1×23+1×20+1×2-2+1×2-3=9.375
2.十六进制数的表示法
十六进制计数法的特点如下。
1)需要16个数字符号:0,1,2,…,9,A,B,C,D,E,F。
2)以16为底,逢16进位。
十六进制数用尾缀H表示。
任意一个十六进制数(NUM)H也都可以按权展开:
(NUM)H=kn-1×16n-1+kn-2×16n-2+…+k1×161+k0×160+k-1×16-1+…+k-m×16-m
其中,16n(如162、161、160、16-1、16-2)称为十六进制数各数位的“权”。
【例1.2】23A8.4H=2×163+3×162+A×161+8×160+4×16-1=9128.25
由于二进制位数太长,不易记忆和书写,所以常采用十六进制的书写方式。4位二进制数可表示1位十六进制数,例如0010对应十六进制数的2,1110对应十六进制数的E。
表1.1列出了一些自然数在十进制、二进制、十六进制这三种不同数制中的对照关系。
表1.1 部分自然数的三种进制表示
1.5.2 数制之间的转换
人们习惯用的进制数是十进制数,而计算机内部唯一能识别的是二进制数,因此,掌握各种数制之间的相互转换是很重要的。
下面介绍几种最常用的进制转换。
1.二进制、十六进制数转换为十进制数
将一个二进制或十六进制数转换成十进制数,只要将此数按权展开,按十进制规律相加,结果就是要转换的十进制数。例如:
101B=1×23+1×21+1×20=11
1EFH=1×162+E×161+F×160=495
2.十进制数转换成十六进制数
十进制数转换为十六进制数时,其整数部分和小数部分是分别转换的。具体如下。
(1)十进制整数转换成十六进制整数
方法:除16取余法。
具体步骤:将十进制数除以16,得到一个商和一个余数;再将商除以16,又得到一个商和一个余数;继续这个过程,直到商等于0为止。每次得到的余数就是对应十六进制数的各位数字。第一次得到的余数为十六进制数的最低位,最后一次得到的余数为十六进制数的最高位。
【例1.3】638=(?)H
得到:638=27EH
(2)十进制小数转换成十六进制小数
方法:乘16取整法。
具体步骤:用16乘以十进制小数,得到一个整数和一个小数部分;再将16乘以小数部分,又得到一个整数和一个小数;继续这个过程,直到余下的小数部分等于0为止;最后将每次得到的整数部分按先后顺序从左到右排列,就得到所对应的十六进制小数。
【例1.4】0.4635=(?)H
得到:0.4635=0.76AH
注意:小数转换不一定能乘尽,只需要算到一定精度的位数即可,因此可能会有一定的误差。转换位数越多,误差越小。
3.二进制数与十六进制数之间的转换
4位二进制数表示的数值相当于1位十六进制数表示的数值。因此彼此间的相互转换极为方便,只要从小数点开始分别向左右展开即可。
二进制数转换成十六进制数:整数部分从右(最低位)向左将二进制每4位分为1组,最高位一组不足4位时应在左边加0,以凑成4位1组,每一组用1位十六进制数表示;小数部分从小数点起从左至右将二进制数每4位分为1组,最低位一组不足4位时应在右边加0,以凑成4位1组,每一组用1位十六进制数表示。
十六进制数转换成二进制数:把每个十六进制数用4位二进制数表示。
【例1.5】1111011.10011B=0111 1011.1001 1000B=7B.98H
6B3EH=0110 1011 0011 1110B
可以看出,十六进制表示的数据信息很容易转换成二进制表示,且十六进制数书写较二进制简短,这就是普遍使用十六进制的原因。
4.十进制数转换成二进制数
十进制数转换二进制数,整数部分除2取余,小数部分乘2取整。具体计算方法与十进制数转换成十六进制数相似。计算过程中,可以先把十进制数转换成十六进制数,再转换成二进制数。
1.5.3 原码、反码、补码
计算机中的数通常有两种:无符号数和有符号数。无符号数由于不带符号,表示时比较简单,直接用它对应的二进制数形式表示。除了无符号数,日常生活中,还有大量有符号数。数的符号有正有负,通常在计算机中表示有符号数时,二进制数的最高位作符号位,“0”表示“+”,“1”表示“-”,其余的位用0和1表示数的大小。这种连同一个符号位在一起作为一个数,称为机器数,它的数值称为机器数的真值。
机器数:机器中数的表示形式,位数通常为8的倍数。
真值:机器数所代表的实际数值。
【例1.6】一个8位机器数与它的真值对应关系如下:
真值:X1=+84=+1010100B X2=-84=-1010100B
机器数:[X1]机=01010100 [X2]机=11010100
机器数在计算机中有三种表示法:原码、反码和补码。
1.原码
原码表示时,在一个字节中,最高位为符号位,“0”表示“+”,“1”表示“-”,而后7位为二进制数的数值位,数值位与真值数值位相同。通常用[X]原表示。设计算机字长是8位,则:
[+127]原=01111111 [+56]原=00111000 [+0]原=00000000
[-127]原=11111111 [-56]原=10111000 [-0]原=10000000
【例1.7】求+63、-34的原码。
|+63|=111111B [+63]原=00111111B
|-34|=100010B [-34]原=10100010B
原码表示简单直观,但0的表示不唯一,有两种数值,即00000000B(+0)和10000000B(-0),加减运算复杂,先要判断符号位,还要比大小,因此在计算机进行数值运算时一般不采用原码运算,为此,引入了反码和补码的概念。
2.反码
反码表示时,正数的反码与原码表示相同,负数的反码其符号位为1,数值位为原码数值各位取反。
【例1.8】求+63、-34的反码。
[+63]原=00111111B [+63]反=00111111B
[-34]原=10100010B [-34]反=11011101B
反码表示“0”时,(-0)的反码为11111111B,(+0)的反码为00000000B,0的表达不唯一。在数值运算中也易出错。
3.补码
补码表示时,正数的补码表示与原码相同,负数的补码的符号位为1,数值位等于反码加1。
【例1.9】求+63、-34的补码。
[+63]反=00111111B [+63]补=00111111B
[-34]反=11011101B [-34]补=11011110B
[+0]补=[+0]反=[+0]原=00000000B=00H
在求(-0)的补码时,我们会发现[-0]原=10000000B,[-0]反=11111111B,加1后得到100000000B(100H),最高位溢出,得到[-0]补=00000000B。
也就是说,用补码表示“0”时,只有一种数值,是唯一的。这样,用补码把减法运算转换为加法运算中结果是完全正确的,加减运算十分方便。
对于一个负数X,X的补码也可用2n-|x|得到,其中n为计算机字长。或者说,一个补码X,所表示的值也可以按权展开:
(NUM)B=-kn-1×2n-1+kn-2×2n-2+…+k1×21+k0×20+k-1×2-1+…+k-m×2-m
【例1.10】求补码C7H所表示的值。
C7H=11000111B=-1×27+1×26+1×22+1×21+1×20=-57
可见,在计算机中,不管是原码、反码还是补码,如果是正数则都相同,区别仅在负数上。
在计算机中,最容易实现的运算是加法运算,而减法运算则较复杂,如果使用补码,则减法运算就可以转化为加法运算。
补码的加减法有如下运算规则:
[X+Y]补=[X]补+[Y]补
[X-Y]补=[X]补+[-Y]补
对于[-Y]补,也可以由[Y]补求出。即把[Y]补的符号与数值位一起取反.末位加1,结果就等于[-Y]补。
【例1.11】完成63+34的补码运算:
【例1.12】完成63-34的补码运算:
表1.2列出了8位二进制数码与无符号数、原码、反码、补码的相对应关系。由表可见8位二进制数码表示的范围为0~255;表示原码为-127~+127;表示反码为-127~+127;表示补码为-128~+127。
表1.2 数的表示方法
在计算机中,得到一个数的反码很容易,因而得到一个数的补码也很容易。使用了补码后,运算时符号位与有效值部分一起参加运算,从而简化了运算规则,很多运算变得容易;补码表示法能使减法运算转换为加法运算,简化了计算机的硬件结构,控制线路变得简单;因而,目前多数计算机采用补码存储和补码运算,其结果也是补码形式。
1.5.4 二进制数的算术运算
在计算机运算中算术运算主要是二进制数的运算。而二进制的算术运算与十进制的算术运算原则基本相同,不同的是二进制进位计算时逢二进一,借位时借一当二。
1.无符号数的算术运算
无符号数的算术运算有加、减、乘、除,其运算规则与十进制相同。运算规则如下:
加法规则:0+0=0;0+1=1;1+0=1;1+1=0(进1)。
乘法规则:0×0=0;0×1=0;1×0=0;1×1=1。
无符号数因为不用符号位,8位全部用来表示数据,所以这种方法可以表示的数据范围是0~255。
2.有符号数的算术运算
通常计算机内的有符号数皆为其补码形式,所以补码的算术运算规则就是有符号数的算术运算规则。
若两数作加减法,可不考虑两数的符号,直接用补码相加减,如果计算结果在字长为8位的计算机中,并且计算结果不超出补码的计数范围(-128~+127),这时的进位可以视为自然丢弃。在计算机处理中,这种自然丢弃并不影响结果的正确性。如果结果超出补码的计数范围则其进位称之为溢出。
溢出与自然丢弃的判别方法是如果在计算中第7位与第8位同时产生进位,即所谓双进位,则这种进位属于允许的自然丢弃;如果只有第7位或第8位产生进位,即只有单进位,则这种进位属于溢出。有时候判断进位也用符号位来判别,即两个符号相同的数进行加法运算,其结果符号与参加运算的数的符号不同,则产生溢出;两个不同符号的数进行减法运算,其结果符号与被减数不同,则产生溢出。溢出表示其数值超出计算机字长所能表示的范围,运算结果必然是错误的,因而也是不允许的。通常计算机用溢出标志位来判断溢出。
当然,溢出主要是指有符号二进制数进行算术运算可能产生的一种现象,对于无符号数来说,第8位不是符号,只有第8位进位才称为进位,因而不采用溢出这个概念。
【例1.13】X=54,Y=36,求X-Y。
【例1.14】X=88,Y=48,求X+Y。
两个正数相加,和为负,错。
溢出判断可以依据如下方法:溢出=Cs+1⊕Cs(即:结果为0无溢出,结果为1有溢出)。
判断补码运算是否产生溢出,也有一种比较简单的方法。假设参加相加的两个数及结果都用补码,且将结果的进位位丢失,则有:
● 两个正数相加得负数,有正溢出。
● 两个负数相加得正数,有负溢出。
有三种情况下无溢出:①两个正数相加得正数;②两个负数相加得负数;③一个正数与一个负数相加。
1.5.5 常用编码
1.术语
● 数码:代表一个确切的数字,如二进制数、八进制数等。
● 代码:特定的二进制数码组,是不同信号的代号,不一定有数的意义。
● 编码:n位二进制数可以组合成2n个不同的信息,给每一个信息规定一个具体码组,这个过程叫作编码。
2.二-十进制编码(BCD码)
十进制是人们在生活中最习惯的数制,人们通过键盘向计算机输入数据时,常用十进制数输入,显示器向人们显示的数据也多为十进制形式。但计算机能直接识别与处理的却是二进制数,所以就必须对十进制数进行编码。二-十进制编码又称为BCD(Binary Coded Decimal Code)码,即用二进制表示十进制。这种编码的特点是保留十进制的权,数字则用二进制表示。即仍然是逢十进一,但又是一组二进制代码。常用的8421BCD码如表1.3所示。
表1.3 常用的BCD码
例如,十进制数123的BCD码为0001 0010 0011;十进制数4.56的BCD码为0100.0101 0110。
BCD码在单片机应用中十分重要,特别是在数码显示中应用很多。
3.二进制码
● 自然二进制码:有权码,每位代码都有固定权值,结构形式与二进制数完全相同。
● 循环二进制码:无权码,每位代码无固定权值,任何相邻的两个码组中,仅有一个代码不同。
循环二进制码又称格雷码,属于可靠性编码,是一种错误最小化的编码,因为它大大地减少了由一个状态到下一个状态时电路中的混淆。由于这种编码相邻的两个码组之间只有一位不同,因而在用于模/数转换中,当模拟量发生微小变化而可能引起数字量发生变化时,格雷码仅改变一位,这样与其他码同时改变两位或多位的情况相比更为可靠,即可减少出错的可能性,这就允许代码电路能以较少的错误在较高的速度下工作。
自然二进制码和循环二进制码如表1.4所示。
4.ASCII码
在计算机中除了数值之外,还有一类非常重要的数据,那就是字符,如英文的大小写字母(A,B,C,…,a,b,c,…)、数字符号(0,1,2,…,9)以及其他常用符号(如:?、=、%、+等)。在计算机中,这些符号都是用二进制编码的形式表示。
现在的计算机中字符数据的编码通常采用的是美国标准信息交换代码ASCII码(American Standard Code for Information Interchange)。基本ASCII码标准定义了128个字符。ASCII码常用于计算机与外部设备的数据传输。常用字符的ASCII码如表1.5所示。
表1.4 两种4位二进制编码
表1.5 ASCII码字符表
在ASCII码中,前两列主要是一些操作码,如NUL表示空格,ACK表示打印校验等。此外,ASCII码中包括了数码(0~9)、英文大写字母(A~Z)、英文小写字母(a~z)、特殊符号(!,?,#等)。
在表1.5中,左面和上面为相应字符的ASCII的编码值,其中上面为高三位二进制码,左面为低四位二进制码。例如,字母‘A’用ASCII编码,其值为1000001,即41H,而符号‘!’的ASCII编码值为0001010,即0AH。
注意:在ASCII码中,字母的大、小写代码只有b5位有区别,因而要进行大小写的转换十分方便,如‘A’的代码为01000001,而‘a’的代码则为01100001,在运算中,大写字母的代码只需加上32(100000B)就成为小写字母,而小写字母减去32就成为大写字母。
在8位微型计算机中,信息通常是按8位来存储和传送的,而ASCII码共7位,因此,最高位通常定义为0(除非另有规定,如作奇偶校验位)。如果最高位为1,就不再是ASCII码了,而可以成为其他代码,如在汉字系统中,两个最高位为1的字节组合在一起(16位)就可代表一个汉字。