1.1 计算机中的数制与编码
1.1.1 数制与数制转换
1.数制的基本概念
人们在生产实践和日常生活中,创造了多种表示数的方法,这些数的表示规则称为数制,其中按照进位方式计数的数制称为进位计数制。
(1)十进制计数制。
十进制计数制的计数规则是“逢十进一”。任意一个十进制数值都可用0、1、2、3、4、5、6、7、8、9共10个数字符号组成的字符串来表示,这些数字符号称为数码,数码处于不同的位置(数位)代表不同的数值。例如,十进制数819.18可以写成819.18=8×102+1×101+9×100+1×10-1+8×10-2。
上式称为数值的按位权展开式,其中10i(102对应百位,101对应十位,100对应个位,10-1对应十分位,10-2对应百分位)称为十进制数位的位权,10称为基数。
(2)二进制计数制。
二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。在计算机科学中,常用的进制还有八进制和十六进制。
2.数制之间的转换
(1)任意进制数转换成十进制数。
利用按位权展开的方法,可以把任意数制的一个数转换成十进制数,如上面展开式所示。任意R进制计数制的值都可表示为:各位数码本身的值与其所在位位权的乘积之和。例如:
十进制数256.16的按位权展开式为
256.16D=2×102+5×101+6×100+1×10-1+6×10-2
二进制数101.0l的按位权展开式为
101.01B=1×22+0×21+1×20+0×2-1+1×2-2
八进制数307.4的按位权展开式为
307.4O=3×82+0×81+7×80+4×8-1
十六进制数F2B的按位权展开式为
F2BH=15×162+2×161+11×160
(2)十进制数转换为任意进制数。
如果需要将一个十进制数转换成一个R进制数,对于整数部分采用的是“除R取余法”,对于小数部分采用乘R取整法”。图1.1为将十进制整数转换成二进制整数的“除2取余法”。
在图1.1中将十进制数215用2去除所得的商数,直到商等于0为止。每次相除所得的余数便是对应的二进制整数的各位数码。第一次得到的余数为最低有效位,最后一次得到的余数为最高有效位,由此得到215对应的二进制数为11010111B。可以理解为:除2取余,自下而上。
上述将十进制数转换成二进制数的方法,同样适用于十进制与八进制、十进制与十六进制数之间的转换,只是使用的基数不同。

图1.1 “除2取余法”
(3)二进制数与八进制或十六进制数的转换。
用二进制数编码,存在这样一个规律:n位二进制数最多能表示2n种状态,分别对应0,1,2,3,…,2n-1。可见,用3位二进制数就可对应表示1位八进制数。同样,用4位二进制数就可对应表示1位十六进制数。因此,将二进制转换成八进制时只要每3位进行转换;而将二进制转换成十六进制时只要每4位进行转换即可。
如将二进制数11101010011B转换成八进制数,按上述方法,从小数点开始向左每3位一组分隔,不足3位补0,得到011101010011,对应八进制数为(3523)8。
又如,将十六进制数6AF转换成二进制数,按每1位十六进制数对应4位二进制数,6AF对应的二进制数是011010101111,即11010101111B。
1.1.2 计算机中的数值数据
1.机器数与真值数
在计算机中,因为只有0和1两种形式,所以数的正、负号,也必须以0和1表示。通常把一个数的最高位定义为符号位,用0表示正,1表示负,称为数符,其余位表示数值。
例如,一个8位二进制数-0101100,它在计算机中表示为10101100,如图1.2所示。
这种把在机器内存放的正、负号数码化的数称为“机器数”,而它代表的数值称为此机器数的“真值”。例如,上面10101100为机器数,而-0101100为此机器数的真值。

图1.2 机器数
数值在计算机内采用符号数字化后,计算机就可以识别和表示数符。但若将符号位同时和数值参与运算,由于两操作数符号的问题,有时会产生错误的结果,而要考虑计算结果的符号问题,将增加计算机实现的难度。为解决此类问题,在计算机中对符号数采用了三种编码方法,即原码、反码和补码,其实质就是对负数表示的不同编码。
2.原码、反码、补码
原码、反码和补码这三种表示方法的符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。简单起见,这里只以整数为例,而且假定字长为8位。
(1)原码。
整数X的原码指其符号位用0表示正数、1表示负数,其数值部分就是X绝对值的二进制表示。X的原码可以用[X]原表示。
例如:
[+1]原=00000001 [+127]原=01111111
[-1]原=10000001 [-127]原=11111111
可以看出,8位原码表示的最大值为27-1,即127,最小值为-127,即8位原码表示的数的范围为-127~127。
采用原码表示方法,编码简单,与真值转换方便。但原码也存在如下的问题:
①在原码表示中,0有两种表示形式,即
[+0]原=00000000 [-0]原=10000000
零的二义性,给机器判断带来了麻烦。
②用原码做四则运算时,符号位需要单独处理,增加了运算规则的复杂性。原码的不足之处促使人们寻找更好的编码方法。
(2)反码。
对于整数X,正数的反码就是其原码;负数的反码是将原码中除符号位以外的每一位取反。X的反码可以用[X]反表示。
例如:
[+1]反=00000001 [+127]反=01111111
[-1]反=11111110 [-127]反=10000000
反码运算也不方便,因此很少直接使用。一般,反码都是用作求补码的中间码来使用的。
(3)补码。
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
正数的补码就是其原码;对于负数补码,其符号位为1,对数值位取反+1即可求得其补码。或者直接地,负数补码就是其反码+1。通常用[X]补表示补码。
例如:
[+1]补=00000001 [+127]补=01111111[-1]补=11111111 [-127]补=10000001
在补码中,0有唯一的编码,即:
[+0]补=00000000
[-0]补=[-0]反+1=11111111+1=00000000
因而可以用多出来的一个编码10000000来扩展补码所能表示的数值范围,即将负数最小值从-127扩大到-128。这里的最高位1既可以看作是负数的符号位,又可以表示为数值位,其值为-128。这就是补码与原码最小值不同的原因。
已知一个数的补码,求原码的操作其实就是对该补码再求补码。如果补码的符号位为0,表示是一个正数,其原码就是补码;如果补码的符号位为1,表示是一个负数,那么求给定的这个补码的补码就是要求的原码。
如已知一个补码为11111001,求其对应的原码。因为符号位为1,表示是一个负数,所以该位不变,仍为1,其余七位1111001取反后为0000110;再加1,所以是10000111(-7)。
利用补码可以方便地实现正负数的加法运算,规则简单,在数的有效表示范围内,符号位如同数值一样参加运算,也允许产生最高位的进位(被丢弃),所以使用很广泛。
3.数的定点和浮点表示
如果两个数运算的结果超出了该类型可表示的范围(有符号的8位二进制位,可表示的最大值是127),这种情况称为“溢出”。为了避免溢出情况的发生,当要存放一个很大或很小的数时,通常会采用浮点数的形式存放。计算机内表示的数,主要有定点小数、定点整数与浮点数三种类型。
(1)定点小数的表示法
定点小数是指小数点准确固定在数据某一个位置上的小数。一般把小数点固定在最高位的左边,小数点前边再设一位符号位。按此规则,任何一个小数都可以写成:
N=NSN-1N-2…N-M
其中NS为符号位,如图1.3所示,即在计算机中用M+1个二进制位表示一个小数,最高(最左)一个二进制位表示符号(通常用0表示正号,1表示负号),后面的M个二进制位表示该小数的数值。小数点不用明确表示出来,因为它总是定在符号位与最高数值位之间。对用M+1个二进制位表示的小数来说,其值的范围为|N|≤1-2-M。

图1.3 定点小数
(2)整数的表示法。
整数所表示的数据的最小单位为1,可以认为它是小数点定在数值最低位(最右)右边的一种表示法整数分为带符号整数和无符号整数两类。对于带符号整数,符号位放在最高位。可以表示为:
N=NSNM-1NM-2…N2N1N0
其中NS为符号位,如图1.4所示。

图1.4 整数
对于用M+1位二进制位表示的带符号整数,其值的范围为|N|≤2M。
对于无符号整数,所有的M+1个二进制位均看成数值,此时数值表示范围为0≤N≤2M+1-1。在计算机中,一般用8位、16位和32位等表示数据。一般定点数表示的范围都较小,在数值计算时,大多采用浮点数。
(3)浮点数的表示法。
浮点表示法对应于科学(指数)计数法,如110.011可表示为:
N=110.011=1.10011×210=11001.1×2-10=0.110011×2+11
在计算机中一个浮点数由两部分构成:阶码和尾数。阶码是指数,尾数是纯小数,其存储格式如图1.5所示。

图1.5 浮点数存储格式
阶码只能是一个带符号的整数,它用来指示尾数中的小数点应当向左或向右移动的位数,阶码本身的小数点约定在阶码最右面。尾数表示数值的有效数字,其本身的小数点约定在数符和尾数之间。在浮点数表示中,数符和阶符都各占一位,阶码的位数随数值表示的范围而定,尾数的位数则依数的精度要求而定。
注意:
浮点数的正、负是由尾数的数符确定,而阶码的正、负只决定小数点的位置。