1.2.2 信息的表示及转换

与人脑不同,信息进入计算机内部都要转换为数据,其中就涉及数值计算的问题,这就涉及用什么进制数的问题。ENIAC用的是人类所熟知的十进制数。当时,匈牙利美籍数学家冯·诺依曼在研制速度比ENIAC更快的名为IAS的计算机时,感觉十进制的表示和实现方式十分麻烦,于是提出了用二进制表示及程序存储、程序控制等重要思想和原理。直到今天,人们仍旧沿用冯·诺依曼的思想和原理设计和制造计算机,冯·诺依曼也因此被后人尊称为“现代计算机之父”。

相比于十进制,计算机采用二进制的优点很多,如运算简单、电路易于实现、通用性强、占用空间小、消耗能量低、机器可靠性高等。

不仅是数值使用二进制表示和运算,文字、声音、图像、视频等在计算机内部也是采用二进制形式的代码来表示的。而处在计算机外部的人类熟悉的却是十进制数和文字、声音、图像、视频等,这是个矛盾,需要通过转换来解决。图1-3直观地表示了这一转换过程。

图1-3 各类信息在计算机中的转换

以下介绍各类信息在计算机中的具体转换过程。

1.进制数之间的转换

进制数之间的转换主要讨论十进制数值与二进制之间的转换。实际应用中还会涉及数值的正号“+”、负号“-”以及小数点“.”如何转换成二进制数的问题。计算机语言程序设计课有这方面的内容,本书对这些问题不展开讨论,仅就一般的转换方法进行介绍。由于二进制数的阅读和书写均不方便,实际应用中人们也常用八进制或十六进制形式来表示。因此,下面一并对上述4种进制之间的转换方法进行介绍。

所谓的进制也就是进位制,是人们利用符号进行计数的科学方法。R进制就表示某一位置上的数运算时满R就向高一位进1。表1-8显示了常用进位制的基础知识。

表1-8 常用进位制基础知识

其中D、B、O、H分别是十进制、二进制、八进制、十六进制英文单词的首个字母。十进制中的10、11、12、13、14、15在十六进制中分别是6个不可拆分的数,依次用A、B、C、D、E、F表示。

对单个数码而言,有这样的基本关系:小进制的单个数码与大进制的相同数码相等。例如:(1)B=(1)O=(1)D=(1)H;(7)O=(7)D=(7)H;(9)D=(9)H,等等。

对于十进制数(123456.789)10,它共包含1个10万、2个万、3个千、4个百、5个十、6个一、7个十分之一、8个百分之一和9个千分之一,因此可以将它展开为和的形式:

(123456.789)10=(1×105+2×104+3×103+4×102+5×101+6×100+7×10-1+8×10-2+9×10-3D

同理,对任何一个R进制数(anan-1…a1a0.a-1a-2…a-mR,有如下类似的结论:

(anan-1…a1a0.a-1a-2…a-mR=(an×Rn+an-1×Rn-1+…+a1×R1+a0×R0+a-1×R-1+a-2×R-2+…+a-m×R-mD

(以下简称“展开式1”)

注意,左边是R进制数,而右边是十进制数,这是数制转换的重要依据。

(1)R进制转换为十进制

当R=10时,是将一个十进制数分解为计数单位加权和的形式。

当R=2、8或16时,只需要根据展开式1直接展开再进一步计算即可。例如:

(10110.101)B=(1×24+0×23+1×22+1×21+0×20+1×2-1+0×2-2+1×2-3D=(22.625)D

(123.4)O=(1×82+2×81+3×80+4×8-1D=(83.5)D

(1AB.C)H=(1×162+10×161+11×160+12×16-1D=(427.75)D

(2)十进制转换成R进制

当R=10时,是将展开式1由右边推出左边,实际上是将各个计数单位相加的结果。

当R=2、8或16时,国内几乎所有的同类教材都采用“整数除以R取余,小数乘以R取整”的方法,这是计算机编程所用的算法,本书不做介绍,读者可通过网络或参考其他文献学习。就手工计算而言,上述方法有如下不足:一是整数、小数部分算法不同,高低位顺序有别,难掌握,易弄错;二是计算烦琐,数值稍大就会耗费大量纸张,不环保。

以下介绍的最大幂算法是针对手工计算设计的方法,其基本依据来自上述展开式1,主要思路是先将十进制数表示成展开式1右边的形式,进而得到左边,也就是最终的结果。这种方法所需要的基础知识如表1-9所示。

表1-9 以2、8或16为底的幂

十进制数(S)D转换成R(R=2,8或16)进制数的最大幂算法步骤:

①将(S)D分解为两部分,(S)D=(q×Rm+S1D。其中,Rm是不超过S的最大幂,q是使q×Rm不超过S的最大幂个数,S1是待分解部分。

②若S1=0或满足精度要求则结束分解过程,否则对S1重复上述步骤①。

③按照展开式1右边的格式进行调整并逆推得出左边,进而得到最终结果。

例如:分别将十进制数130.625转换成二进制数、八进制数和十六进制数。

(130.625)D=(27+2.625)D(27=128是不超过130.625的最大幂,有1个)

       =(27+21+0.625)D(21=2是不超过2.625的最大幂,有1个)

       =(27+21+2-1+0.125)D(2-1=0.5是不超过0.625的最大幂,有1个)

       =(27+21+2-1+2-3D(2-3恰好等于0.125,分解过程结束)

       =(1×27+0×26+0×25+0×24+0×23+0×22+1×21+0×20+1×2-1+0×2-2+1×2-3D

(化成按展开式1右边的样子,熟练后此步可省略,下同)

       =(10000010.101)B(逆推得出左边)

(130.625)D=(2×82+2.625)D(82=64是不超过130.625的最大幂,有2个)

       =(2×82+2×80+0.625)D(80=1是不超过2.625的最大幂,有2个)

       =(2×82+2×80+5×8-1D(8-1=0.125,0.625恰好是5个8-1

       =(2×82+0×81+2×80+5×8-1D=(202.5)O

(130.625)D=(8×161+2.625)D(161=16是不超过130.625的最大幂,有8个)

       =(8×161+2×160+0.625)D(160=1是不超过2.625的最大幂,有2个)

       =(8×161+2×160+10×16-1D(16-1=0.0625,0.625恰好是10个0.0625)

       =(82.A)H

整数部分总是可以完全分解的。若小数部分无法完全分解,只需分解到满足精度要求的步骤即可。

(3)二进制与八进制或十六进制的转换

可以利用上面介绍的方法,以十进制为桥梁间接实现二进制与八进制或十六进制的转换,下面介绍的是直接转换的方法。

八进制数、十六进制数可以看作对二进制数的压缩,而二进制数可以看作八进制或十六进制数的展开。由于23=8,24=16,由此得到如下直接转换法:

①将二进制数转换成八进制数,只需以小数点为中心向左向右两边分组,每3位为一组,不足3位外侧补0,然后各组分别根据展开式1计算即可。

②将二进制数转换成十六进制数,只需以小数点为中心向左向右两边分组,每4位为一组,不足4位外侧补0,然后各组分别根据展开式1计算即可。

③将八进制或十六进制数转换成二进制数,只需分别将数中的每一位分解为3位(对八进制数)或4位(对十六进制数)即可,分解可参考十进制转换为R进制的方法进行。

例如:将二进制数(10101011.110101)B分别转换为八进制数和十六进制数。

(10101011.110101)B=(010101011.110101B(每3位做一组,不足3位外侧补0)

           =(253.65)O

(各组按展开式1分别计算,如(110)B=(1×22+1×21+0×20D=(6)D=(6)O

(10101011.110101)B=(10101011.11010100B(每4位做一组,不足4位外侧补0)

           =(AB.D4)H

(各组按展开式1分别计算,如(1101)B=(1×23+1×22+0×21+1×20D=(13)D=(D)H

又如,分别将(23.45)O和(AB.45)H转换成二进制数。

由于(2)O=(2)D=0×22+1×21+0×20=(010)B(3)O=(3)D=(0×22+1×21+1×20D=(011)B(补足3位)

同理(4)O=(4)D=(100)B,(5)O=(5)D=(101)B

所以 (23.45)O=(010 011.100 101)B

类似的,由于(A)H=(10)D=1×23+0×22+1×21+0×20=(1010)B

(B)H=(11)D=1×23+0×22+1×21+1×20=(1011)B

(4)H=(0100)B(5)H=(0101)B(要补足4位)

所以(AB.45)H=(1010 1011.0100 0101)B

表1-10列出了一位八进制数或十六进制数与二进制数的对应关系。

表1-10 一位八进制数或十六进制数与二进制数的对应关系

由于数值进入计算机内部后都转换为二进制数,所以数值的运算就转换为二进制的运算。表1-11所示为二进制的基本运算规则。

表1-11 二进制基本运算规则

2.西文字符的转换

字符是指文字符号,包括那些不参加数值运算的数字符号,如身份证号码、车牌号等。西文字符是计算机中最基本的字符。图1-3表明,西文字符进入计算机内部后都要变为ASCII码。这里的ASCII是American Standard Code for Information Interchange的缩略词,即美国信息交换标准码,是美国国家标准局制定的西文字符编码标准,后来被国际标准化组织指定为国际标准。

ASCII码有7位码和8位码两个版本。国际通用的是7位版本,该版本每个字符都占8个二进制位(即1字节),但实际只用低7位,最高位全置为0,因此共表示27=128个不同的字符。表1-12所示为完整的7位ASCII码表。

表1-12 7位ASCII码表

对7位ASCII码表的基本理解:字符对应的高4位和低4位编码连起来就是计算机内该字符的ASCII码。例如,“0”这个字符在计算机内是用00110000这个代码来表示的。如果将其看成二进制数,对应的十进制数是48(又称为“0”的ASCII码值))。在这里可以看到作为数值的0与作为字符的0在计算机内是当作不同的数据来处理的,其代码是完全不同的。又如,DEL删除键在计算机内是用01111111来表示的,对应的十进制数是127,即其ASCII码值是127。

7位ASCII码表有34个不可打印(显示)的控制字符(前两列32个+SP(空格)+DEL),其余94个均可打印(显示)。

字符ASCII值大小比较:对字符排序时需要按照字符的ASCII码值进行比较。表中排在前面的字符其ASCII码值比排在后面的小,因此“空格(SP)”<“阿拉伯数字”<“大写字母”<“小写字母”<“删除键(DEL)”;相邻字符前一个比后一个少1,如“0”的ASCII码值是48,则“1”的ASCII码值就是49;同一个字母,大写的比小写的少32,如A的ASCII码值是65,a的ASCII值就是97。

通过以上介绍可知,西文字符进入计算机内需要转换为ASC II码。要将字符显示在屏幕上或从打印机打印出来,需要将ASCII码转换为西文字形码。这些字形码放在计算机硬盘的某个地方,如C盘下windows文件夹下的Fonts子文件夹中。这些知识后面会介绍。

从西文字符转换成ASCII码进入计算机内部,到将ASCII码转换成西文字形码在屏幕上显示,是由计算机软硬件在极短时间内自动完成的,只需输入字符即可。

3.汉字字符的转换

ASC II码只能解决西文字符输入计算机的问题。要想在计算机里使用汉字,就要让计算机识别汉字,同样需要制定汉字的转换标准。

由于世界上使用汉字的地区和国家较多,汉字编码标准也较多。表1-13所示为对部分汉字编码标准的简单介绍。

表1-13 部分汉字编码标准

现在来重点讨论国标码(即GB 2312—1980)。国标码用两个字节共16位代码表示一个汉字。由于汉字多达6763个,数量庞大,不像ASCII码那样只有128个。如何直观显示各个汉字的编码是个大问题。我国的做法是根据各个汉字的国标码将这6763个汉字放到一个94行、94列名为汉字区位码表的二维表中,如表1-14所示。

表1-14 汉字区位码样表

每个汉字由它所在的区号(行号)和位号(列号)来确定。由区号和位号构成的一串数字就叫作区位码。例如,“中”字的区位码是5448,这里区号是54,位号是48,都是十进制数。

国标码与区位码的关系是:国标码=区位码+(20 20)H(注意:计算时进制要一致)

例如,求“中”的国标码。因(54)D=(3×161+6×160D=(36)H(区号转换为十六进制数)

(48)D=(3×161+0×160D=(30)H(位号转换为十六进制数)

所以,“中”的国标码=(36 30)H+(20 20)H=(56 50)H

将(56 50)H按位转换成二进制后就是(01010110 01010000)B

汉字编码标准本质上是用什么二进制形式的代码来表示一个汉字的问题。与英文不同,汉字是象形文字,不但字符个数多,而且组成汉字的部件千差万别,汉字结构的复杂性决定了其处理过程远比英文复杂。下面以图1-3为基础来介绍汉字的处理过程。

(1)汉字输入码

要输入英文,只需按键盘上相应的字母键即可,没必要额外的输入法。但键盘上的键比汉字的数目少得多,要输入汉字就得使用某种输入法,用键的组合来表示一个汉字。目前常用的输入法有:音码、形码、语言输入、手写输入、扫描输入等。

利用某种输入法将汉字输入计算机所用的代码称为汉字输入码,又称外码。例如,用搜狗输入法在键盘上输入txm,得到“同学们”,也得到“条形码”这3个字,那么txm既是“同学们”的输入码,又是“条形码”的输入码。若打入tongxuemen也得到“同学们”3个字,所以tongxuemen也是“同学们”的输入码。也就是说,同一个字或词可以有不同的输入码,而不同的字或词也可以有相同的输入码。

输入码负责把汉字送入计算机内部。

(2)汉字机内码

输入码将汉字送入计算机内部,按理说就应该根据汉字编码标准将汉字转换成对应的二进制形式的代码,但实际处理时会遇到麻烦。例如,国标码(即GB 2312)规定每个汉字用两个字节来表示,每个字节的最高位都是0,而ASCII码规定每个字符用一个字节表示,每个字节最高位也是0。也就是说,表示汉字的两个字节中的任一个都可以是一个ASCII码,这在处理过程中会导致冲突。为了避免这种冲突,人们实际的做法是将国标码两个字节的最高位由0改为1,以便与西文的ASCII码进行区分。

将国标码的两个字节最高位由0变为1所得编码称为汉字机内码。计算机内部处理(内存中)、存储时(外存中)用的都是汉字机内码。可以得出,汉字国标码与汉字机内码存在下列关系:

汉字机内码=汉字国标码+(10000000 10000000)B

     =汉字国标码+(80 80)H

例如,“中”字的机内码=(56 50)H+(80 80)H=(D6 D0)H=(11010110 11010000)B,也就是说“中”字在计算机内存和外存都是用11010110 11010000这个16位代码来表示的。其他汉字在计算机内部也都将转换成某个16位二进制形式的代码,占2个字节。

根据国标码与区位码的关系,还可以进一步得到汉字机内码与区位码的关系式:

汉字机内码=汉字国标码+(80 80)H=区位码+(20 20)H+(80 80)H=区位码+(A0 A0)H

(3)汉字字形码

汉字机内码只是计算机内部处理、存储用的。如果要将汉字显示在屏幕上或从打印机打印出来,需要将汉字机内码转换成汉字字形码。汉字字形码也叫汉字字库、汉字字模等,用于汉字的显示或打印。与西文字形码类似,汉字字形码也是放在计算机硬盘的某个地方,例如,放在C盘下windows文件夹下的Fonts子文件夹中。

汉字字形码分点阵字形和矢量字形两种。点阵字形用点来表示汉字,有16×16点阵、24×24点阵、32×32点阵、48×48点阵等。点阵字形质量不高,放大就有明显的锯齿状。

矢量字形通过数学曲线、数学公式来描述汉字轮廓特征,质量高,放大不会变形。

4.声音、图像、视频的转换

数字化之前,声音、图像、视频等都是模拟信号(用连续变化的物理量表示的信息),它们是不能被计算机所识别的。要让计算机识别它们,就需要模数设备(即A/D设备,指将模拟信号转换为数字信号的设备)进行转换,将模拟信号的声音、图像、视频转换为数字信号的声音、图像、视频等。而当要在模拟信号设备(如音箱、显示器等)播放声音、视频或显示图像时,则需要数模设备(即D/A设备,指将数字信号转换为模拟信号的设备)进行转换。人们用手机拍的照片或视频之所以能放进计算机,是因为手机具有模数转换功能,自动将所拍的照片和视频进行了转换。

数字化后,声音、图像、视频都变成二进制形式的代码,即0、1组成的代码串。