1.3 数制
之前,我们提到数字计算机处理的是离散信息,并都采用二进制形式表示。计算中的操作数都是二进制数或者是用二进制形式表示的十进制数。字母表中的字母也有相对应的二进制编码。本章的余下内容将介绍二进制、二进制计算以及以后章节会用到的一些二进制编码。对于通用计算机来说,这些内容是非常重要的,它的每个部件都会用到这些知识,当然在某些输入输出设备中还会提及机械操作和模拟(与“数字”相反)电路。
十进制数是人们日常使用的计数法,采用一串数字来表示数的大小,其中每个数字根据它所在的位置而具有不同的权重,这些权重是10的幂。例如,十进制数724.5包含有7个100、2个10、4个1以及5个10分之1,其中的百位、十位、个位、十分位就是每个数字的权位,其权重大小是10的幂。整个十进制数的大小可以这样计算:
724.5=7×102+2×101+4×100+5×10-1
这种数字表示方法只需要知道每位数字以及其对应的权位。一般而言,一个有n位整数m位小数的十进制数可以用如下系数形式表示:
An-1 An-2 …A1 A0. A-1 A-2…A-m+1 A-m
其中每一个系数Ai都是0、1、2、3、4、5、6、7、8、9这十个数字中的一个,下标i表示该系数的权位,其权重就是10i。
十进制数的基底(base或radix)是10,因为系统中采用了10个不同的数字,数字权位的权重是10的幂。一般而言,一个基底为r的进制系统使用r个不同的数字:0,1,2,…,r,并可以用如下r的不同次幂的多项式表示:
An-1 rn-1+An-2 rn-2+…A1 r1+A0 r0+A-1 r-1+A-2 rn-2+…A-m+1 r-m+1 A-m r-m
采用按位计数法来表示数字时,只需要将多项式的各项系数以及小数点写成如下形式即可:
An-1 An-2 …A1 A0. A-1 A-2…A-m+1 A-m
通常,“.”为小数点,An-1为最高有效位(most significant digit,msd),A-m为最低有效位(least significant digit,lsd)。当m=0时,最低有效位A-0=A0。为了能清晰地区分数字的进制,通常用小括号将系数括起来,并在括号的右下方用一个下标数字提示本数字的进制。当然,如果从上下文能清楚地知道数字的进制,那么这个括号也可以不要。下面是一个n为3,m为1的五进制数以及其转换为十进制形式的例子。
(312.4)5=3×52+1×51+2×50+4×5-1=75+5+2+0.8=(82.8)10
注意,所有没有特意说明进制的数字都是按十进制进行计算的。在五进制系统中,只能使用5个数字,因此系数的值只能是0、1、2、3或4。
我们还可以采用另一种计算步骤较少的方法进行进制转换,这种方法基于一连串的幂因子分解。
(...((An-1r+An-2)r+(An-3)r+...+A1)r+A0
+(A-1+(A-2+(A-3+...+(A-m+2+(A-m+1+A-mr-1)r-1)r-1…)r-1)r-1)r-1
对于上面的例子,我们有:
(312.4)5=((3×5+1)×5)+2+4×5-1=16×5+2+0.8=(82.8)10
除了十进制,在计算机系统中还有3种常用的进制:二进制、八进制以及十六进制,它们的基底分别为2、8和16。
1.3.1 二进制
二进制数字系统的基底为2,数字只有两个:0和1。一个二进制数,比如11010.11是由一串1和0来表示的,如果是小数,则还有一个小数点。二进制数转化为十进制形式很容易,只需将二进制数字按2的幂级数形式展开即可,例如,
(11010)2=1×24+1×23+0×22+1×21+0×20=(26)10
前面我们提到过,二进制数字中的每一个数称为一位(bit)。当某一位为0,即表示这一位在转换求和的过程中没有任何贡献。所以,将二进制数转化为十进制的形式只需要将所有值为1的位所对应的2的指数值相加即可,例如,
(11010.11)2=32+16+4+1+0.5+0.25=(53.75)10
表1-2列出了2的前24个指数值。在数字系统中我们常称210为1 K,220为1 M,230为1 G,240为1 T。这样,
4 K=22×210=212=4096 16 M=24×220=224=16 777 216
但这种惯用法也会有变化,比如现在人们也常用K、M、G和T分别表示103、106、109和1012。所以遇见K、M、G和T时,我们必须谨慎地理解它们代表的数字大小。
将十进制数变换成二进制数,可以采用一种很方便的方法:将十进制数不断地减去2的指数值。对于一个十进制数N,我们先将N减去一个比它小的2的最大指数值(见表1-2),剩余的数称为N1,我们再将N1减去比它小的2的最大指数值,剩余的数称为N2,一直持续下去,直到剩余的数为0。这样,一个十进制数就可以转换为若干2的指数项,其二进制形式由2的一系列指数项的系数组合形成,这些系数为1或者为0,如果某一个2的指数项用作减数,则其系数为1,否则为0。 这种方法可以用这样一个实际的例子来说明,将625转换成二进制数:
625―512=113=N1 512=29
113―64=49=N2 64=26
49―32=17=N3 512=25
17―16=1=N4 16=24
1―1=0=N5 1=20
(625)10=29+26+25+24+20=(1001110001)2
1.3.2 八进制与十六进制
前面我们提到,所有的计算机与数字系统采用的都是二进制形式。而八进制(基底为8)和十六进制(基底为16)也可以很方便地表示二进制量,因为它们的基底是2的倍数。因为8=23、16=24,所以一个八进制位相当于3个二进制位,一个十六进制位相当于4个二进制位。
用八进制与十六进制表示二进制量,形式上更紧凑,使用起来更方便,二进制位串的长度是八进制或十六进制位串长度的3倍或4倍。所以,大多数计算机手册采用八进制或十六进制来表示二进制量。例如,只需用5个八进制位就可表示一个15位长的二进制串,一个16位的二进制串只需4个十六进制位表示即可。至于是选用八进制还是十六进制,则没有硬性规定,在实际中十六进制的使用更普遍,因为在数字系统中二进制位串通常是4的整倍数长。
八进制的基底为8,数字有8个:0、1、2、3、4、5、6、7。假设一个八进制数为127.4,要求它的十进制形式,只要将它按8的幂级数的形式展开即可:
(127.4)8=1×82+2×81+7×80+4×8-1=(87.5)10
在八进制中没有数字8和9。
在一个基底为r的进制系统中,如果r小于10,一般采用十进制中从0开始的前r个数字;如果r大于或等于10,就选用英文字母来表示大于10的数字。在十六进制中,前10个数字都来自于十进制,而字母A、B、C、D、E、F则分别用于表示10、11、12、13、14、15,例如下面这个十六进制数:
(B65F)16=1×163+6×162+5×161+15×160=(46687)10
表1-3列出十进制、二进制、八进制和十六进制的前16个数字。注意,二进制串按一种规定的模式组成,最低有效位表示0或1,第2有效位表示0或2,第3有效位表示0或4,最高有效位表示0或8。
将二进制转换为八进制非常容易,只需从小数点开始,向左或向右,将二进制位按3位分成一组,然后将每一组用相应大小的八进制数字表示即可。下面就是这种转换过程的演示:
每组二进制位所对应的八进制数字可以从表1-3中查到。如果小数点左方二进制位的长度不是3的倍数,则可在最高位补0,更重要的是,如果小数点右方二进制位的长度不是3的倍数,则必须在最右方补0,这样才会得到正确的转换结果。
将二进制转换为十六进制方法类似,只不过是将二进制串从小数点开始每4位为一组。上面例子中的二进制数转换为十六进制就是:
(010 1100 0110 011.1111 0000 0110)2=(2C6B.F06)16
同样,每组二进制位所对应的十六进制数也可从表1-3中查到。
将八进制数与十六进制数转换为二进制数,正好是以上方法的逆过程。每一个八进制数位可转换成所对应的3个二进制位,多余的0则可去掉。同样,每一个十六进制数位可转换为所对应的4个二进制位。例子如下:
(673.12)8=110 111 011.001 010=(110111011.001010)2
(3A6.C)16=0011 1010 0110.1100=(1110100110.1100)2
1.3.3 数字范围
数字计算机所能表示的数字范围,受到负责信息存储与处理的硬件结构的二进制位个数的限制。通常硬件结构的二进制位个数是2的幂数,比如8、16、32或64。因为受硬件结构的限制,二进制位个数是固定的,所以用固定的二进制位数表示某个数时,没用到的最左前或最右后的二进制位必须置为0,这样,所能表示的数字范围也就是固定的了。
例如,在一个可处理16位无符号整数的计算机中,数字537的二进制表示形式是0000001000011001。这种形式的数能表示的整数范围为0~216―1,也就是从0~65 535。在这台计算机中,对于无符号纯小数,比如0.375,它的二进制表示形式为0.0110000000000000,所能表示的小数范围是0~(216―1)/216,也就是0~0.999 984 741 2。
在以后的章节中,我们还会学习定点小数、有符号数的范围和浮点数。在这些数中,某些二进制位用于表示其他信息,所形成的数字就不是简单的整数和小数了。