第2章 运算方法和运算器 2.1 数据信息和二进制编码 2.1.1数据信息 计算机的基本功能是加工和处理数据信息,为此首先要解决计算机中数据的表示问题。一般地,计算机中使用数据分为两类:数值数据和非数值数据。数值数据具有“量”的概念,可以比较大小,例如温度的高低,湿度的大小等,数值数据还分为整数和实数,整数进一步分为无符号整数和有符号整数,在计算机内部,整数通常使用定点数表示,实数通常使用浮点数表示。非数值数据不表示数量的多少,一般没有大小之分,或大小表示了其他物理意义,如字符、图形、图像、声音和视频的数据等,其中,英文字母数据的大小仅表示其排列的先后顺序。 无论整数、实数这样的数值数据,还是各种各样的非数值数据,都需要转换为二进制数据才能在计算机内部表示和处理。计算机内部采用二进制数据的优势主要有如下几点。 (1)易于物理实现。在二进制表示中仅使用两个数码0和1,从实现上看,任何具有两个明显稳定状态的物理元件都可用来表示这两个数码,因为很多元件或物理量具有两种明显稳定状态,因此易于物理实现,例如晶体管的导通与截止,开关的开和关;电压的高和低、正和负,磁性材料的南极和北极等。 (2)机械可靠性高。对一个物理量,两种稳定状态相比连续变化的状态更能体现出质的差别,并具有更高的稳定性和可靠性,因此,采用二进制码表示,其传输抗干扰能力强,鉴别信息可靠性高。 (3)运算规则简单。二进制数据的四则运算规则简单,以两个数的加法运算规则为例,十进制数有种组合,而二进制只有3种组合,即0+0,0+1,1+1。另外二进制的四则运算最终都可归结为加法和移位运算,这样,运算器线路的设计更加简单,运算速度也更快。 (4)与逻辑判断相适应。二进制符号“1”和“0”恰好与逻辑运算中的“真”(true)与“假”(false)对应,这不仅便于计算机进行逻辑运算,同时也便于人们使用布尔代数理论及工具来分析、设计和综合电子计算机中的逻辑线路。 (5)节省设备。从理论上可以证明,采用三进制最省设备,其次就是二进制。但由于二进制相比三进制具有更多优势,因此,现在电子计算机基本上都采用二进制。 将数据信息用二进制表示称为二进制编码,为了讨论各种二进制编码,首先需要了解进位计数制及几种不同进制之间的转换。 2.1.2进位计数制 1.常用的进位计数制 在表示多位数据时,人们通常采用从低位向高位进位的方式来记数,这就是所谓的进位计数制,简称进制。我们最常使用的进制是十进制,此外还有十六进制和二进制,它们的进位规则是:十进制逢十进一,十六进制逢十六进一,二进制逢二进一。 进位计数制中有两个基本概念:基数和权。其中,基数是使用码字的个数,权是基数的幂,其表示码字在不同位置上的数值。当一个数值使用基数和权表示数值时,其值等于每位上码字与权相乘的累加和。 (1)十进制 十进制使用10个码字0,1,2,3,4,5,6,7,8,9表示,逢十进一,其中,基数是10,权是10的幂次。例如十进制数123.4,可以用带10的下角标表示,通常省略。 (123.4)10 =1x102+2x101+3x100+4x10-1 一般的十进制数可用如下多项式表示 (式2-1) 式中,码字Ki取数码0~9之一,i为整数,m和n为正整数,下面表达中i,m和n取值范围相同,不再赘述。 推广到R进制,R进制使用R个码字0,……,R-1表示, 逢R进一,其中,基数是R,权是R的幂次,一个R进制数表示为: (式2-2) 式中,Ki取码字0~R-1之一。 (2)二进制 二进制使用2个码字0,1表示,逢二进一,其中,基数是2,权是2的幂次,一个二进制数表示为 (式2-3) 式子中,Ki取码字0,1之一。 (3)十六进制 十六进制使用16个码字0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F表示,其中A,B,……,F分别代表十进制的10,11,……,15,逢十六进一,权是16的幂次,一个十六进制数表示为 (式2-4) 式子中,Ki取码字0~F之一。 表2-1汇总了不同进制的基数、码字和权。 表2-1 不同进制的基数、码字和权 基数 码字 权 十进制 10 0,1,2….9 10i 二进制 2 0,1 2i 十六进制 16 0,1,2,…9,A,B,C,D,E,F 16i R进制 R 0,…,R-1 Ri (4)不同进制数值的两种书写方法 为了在书写时区分不同进制,除了使用下角标外,还可以使用后缀,其中后缀D(Decimal)表示十进制数,B(Binary)表示二进制数,H(Hexadecimal)表示十六进制数。例如 十进制数 123.4可表示为(123.4)10,或123.4D; 二进制数 101可表示为 (101)2,或101B; 十六进制数9AC可表示为(9AC)16,或9ACH。 (5)同一个数值的不同进制表示 同一个数值可以用不同的进制表示。表2-2给出了一组数值的十进制、二进制和十六进制表示。 表2-2 三种常用进制之间的对应关系 十进制 二进制 十六进制 十进制 二进制 十六进制 0 0000 0 8 1000 8 1 0001 1 9 1001 9 2 0010 2 10 1010 A 3 0011 3 11 1011 B 4 0100 4 12 1100 C 5 0101 5 13 1101 D 6 0110 6 14 1110 E 7 0111 7 15 1111 F 同一个数值采用不同进制表示时,所需位数是不同的,其特点是:基数越大,使用位数越少。例如10D这个2位十进制数,当用二进制表示时需要4位,即1010B,而当用十六进制表示时则仅需要一位,即AH。一个数值,用十进制和二进制表示所需位数比是log10/log2 ≈3.3,即一个10位的十进制数,当用二进制表示时需大约33位。 2. 进制之间的转换 十进制常用于人们日常生活中数据的表示,二进制用于计算机内部数据的表示,而十六进制则能方便地表达二进制数,下面介绍它们之间的转换。 (1)二进制数转换为十六进制数 对于一般的二进制小数,将其转换为十六进制小数时,每4位二进制数转换为1位十六进制数(见表2-2),并分别转换整数部分和小数部分。具体操作步骤:以小数点为界,整数部分向左,每4位分成1组,当不足4位时,左补0凑够4位,而小数部分向右,每4位分成1组,当不足4位时,右补0凑够4位。这样,二进制小数的总位数是4的倍数,然后将每组转换为一位十六进制数,小数点保留。例如 111010100.011B = 0001 1101 0100.0110B = 1D4.6H (2)十六进制数转换为二进制数 对于一般的十六进制小数,将其转换为二进制小数时,每1位十六进制数转换为4位二进制数,然后,将整数部分最左边的0和小数部分最右边的0去掉。例如 5F4.76H = 0101 1111 0100.0111 0110B =10111110100.0111011B (3)十进制数转换为二进制数 二进制数转换为十进制数,采用按权展开相加法,即将二进制数各位与对应权相乘,然后再计算累加和。按权展开相加法的公式是如下,例如 (式2-5) 1010100.011B = 1x26 + 1x24+ 1x22 + 1x2-2 + 1x2-3 D = 84.375D (4)二进制数转换为十进制数 将一般的十进制小数转换为二进制小数,通常采用基数乘除法,这种算法需要将十进制的整数部分和小数部分别进行转换,整数部分采用除基取余法,小数部分采用乘积取整法,然后再将转换结果拼起来,得到最终的二进制数。 下面以十进制数19.6875D转换为二进制数为例进行说明。 十进制整数部分转换为二进制整数--除基取余法 除基取余法是将十进制数整数部分不断除以基数2并取余数的迭代过程,具体运算规则:将十进制数除以基数2,得到余数,再除以2,又得到余数,……,直到商为0,则先得到的余数为二进制数的低位,后得到的余数为高位。列成竖式计算如下,最终得到整数部分的二进制数:10011 B。 除基取余法的规则可概括为:“除2取余,由下而上”。 十进制小数部分转换二进制小数--乘基取整法 乘基取整法是将十进制小数部分不断乘以基数2并取整数的迭代过程,具体运算规则:将十进制小数部分乘以基数2,取整数,然后再对小数部分乘以2,再取整数,……,直到小数部分为0或者小数位数满足精度,先取到的整数作为二进制小数的高位,后取的整数作为二进制小数的低位。列成竖式计算如下。 0.6875 x 2 = 1.375 取1 (高位) 0.375 x 2 = 0.75 取0 0.75 x 2 = 1.5 取1 0.5 x 2 = 1.0 取1 (低位) 得到小数部分的二进制数为1011B,最后将整数和小数部分的结果拼接起来,得到 19.6875D = 10011.1011B 乘基取整法规则可以概括为:“乘2取整,由上而下”。 由于一般十进制小数不能精确转换为二进制小数,因此要注意乘基取整法的停止条件。如果最后小数为0,则该十进制小数精确地转换为二进制小数,如果最后小数部分不为0,则需要根据小数位数的精度要求,停止迭代过程,例如,如果要求5位二进制精度,则可以多计算一位小数,然后对最低位做“0舍1入”得到最终结果。 例如0.6876D 0.6876 x 2 = 1.3752 取1 (高位) 0.3752 x 2 = 0.7504 取0 0.75 x 2 = 1.5008 取1 0.5008 x 2 = 1.0016 取1 0.0016 x 2 = 0.0032 取0 0.0032 x2 = 0.0064 取0 (低位) 0.6875D = 0.10110B 2.2 数据的编码表示 为了表示有符号的整数、小数等数值数据,以及表示非数值数据,有很多基于二进制的编码方式,下面重点介绍定点数、浮点数、十进制数、英文字母以及汉字等的编码方式。 2.2.1符号位的表示 人们通常使用正负号表示数的正负,那么在计算机内部的二进制数怎样表示正负呢?以有符号的整数为例,在计算机内部需要分别表示其符号和数值,下面介绍真值和机器数的概念。 真值:用正负号表示的数称为这个数的真值,它可以是各种进制形式,多用在手写表达中。 机器数:使用二进制形式,将符号位与数值位整体编码,“先符号位后数值位”形式,符号位在数值位前,用“0”代表正号,“1”代表负号,机器使用方便。注意符号位放在机器字长的最高位。例如,如果机器字长为8位,则符号位应放在第8位上,如果不足8位,则在符号位和数值之间补0使其成为8位。 假设在8位字长的机器中,两个数N1 = +101101B,N2 = -101101B,这是真值表示,而N1’=00101101B,N2’= 10101101B则分别为N1,N2的机器数表示。机器数又有多种编码规则:原码、反码、补码和移码,下面分别加以介绍。 在本章后面例子中,如果没有特殊说明,假设机器字长都是8位。 1.原码   符号位用0表示正数,用1表示负数,数值部分用二进制数的绝对值表示的数称为原码,通常记为[X]原。 上面例子中N1’=00101101B是+101101B的原码,N2’= 10101101B是-101101B 的原码,记为 [+101101B ]原 = 00101101B [-101101B ]原 = 10101101B 当上面例子中N1,N2的真值用十进制表示时,则可以写成 [+45D ]原。= 00101101B [-45D ]原。= 10101101B 【注意】在数学上数字0既不是正数也不是负数,但在机器表示中会有+0和-0两个数,这两个数在机器中都被当做0处理。 [+0 ]原。= 00000000B [-0 ]原。= 10000000B 原码规则简单易懂,与真值转换方便,但不能直接做加、减法运算,例如前面的原码N1’=00101101B和N2’= 10101101B,它们互为相反数,但和不为0。 2.反码 反码规则是:正数的反码与原码相同,负数的反码是符号位不变,数值位逐位取反。 例如,真值+101101B和-101101B,在求出原码后,按照反码规则很容易求出它们的反码。 [+101101B ]原 = 00101101B [+101101B ]反 = 00101101B [-101101B ]原 = 10101101B [-101101B ]发 = 11010010B 反码也不能直接进行加、减法运算,引入反码的主要目的是便于求负数的补码。 3.补码 从真值、原码和反码的定义可知,真值可直接计算,但额外增加“+”和“-”号,计算机表示麻烦,而原码和反码用0,1表示了+”和“-”号,解决了符号表示问题,但它们却不能直接进行加、减法计算。如果通过软件编程或硬件电路实现它们的加、减法运算,需要以各符号位作条件来计算数值部分,计算结果也与符号有关,实现逻辑比较复杂。 是否存在这样一种编码,可以将符号位和数值位作为整体直接运算呢?如果能这样做运算就简单多了。 参考12小时制的指针式钟表,当指针停在6点钟时,如果需要调整到11点,可用两种指针调整方法,一种是向前调11-6 = 5个小时,另一种是向后调6-11+12 = 7个小时。假设向前调记为“+”,向后调记为“-”,那么这两种方法分别调整了+5和-7。为什么调整+5和-7具有相同的结果呢?问题在于钟表指针是在“12”点这个有限域中运转的,每过12个小时,钟表指针指示相同,在数学上12称为模,+5和-7对于模12来说是互补的,或者说+5的补数是-7。相似地,+4和-8是互补的,+3和-9是互补的。 一般地,在有限域中,两个数相加等于模,则称它们互补;有限域中减法运算可以转化为加法运算,即减去一个数等于加上这个数的补数。 每种计算机系统有其固定字长,两个数的加、减运算就是在字长这个模内进行的,一个数减去另一个数,可以变成一个数加上另一个数的补数,补数的引入将加、减法统一成加法运算而不需要考虑负数。 在计算机系统中以字长作为模,将补数称为补码。显然,补码的优点是可以直接进行加、减法运算,下面引入求补码的规则。 求补码的规则1:正数补码的最高位是符号“0”,数值部分是该数本身,负数补码的最高位是符号“1”,数值部分是用模减去该数的绝对值。 根据规则,正数补码就是原码,符号位在最高位,求负数补码要明确所用的模,即计算机字长,例如8位机中,模为28 =1 0000 0000B,负数补码 = 28- 数值的绝对值,在16位机中,模为216=1 0000 0000 0000 0000 B,负数补码 = 216- 数值的绝对值。 【例2-1】 在8位字长计算机中,若X = +101101B ,Y = -101101B ,求 X和Y的补码[X]补、[Y]补。 解: [X]补 =00101101B [Y]补 =100000000B – 101101B( 即28 减101101B ) =11010011B 对于负数,除了按补码规则1计算外,还可以从反码计算,其规则是:负数补码等于其反码+1,由此总结补码的规则2。 求补码的规则2:正数补码的最高位是符号“0”,数值部分是该数本身,负数补码等于其反码+1,即负数补码的最高位是符号“1”,数值部分是各位取反,然后最低位上加1 上例中,-101101的反码是11010010,最低位再加1得到11010011,与第一种方法结果相同。 【注意】 1.求补码时,一般数值位运算不会影响到符号位的变动,只有一种情况例外,即-0,我们定义+0和-0的补码都是0000 0000B(8位字长)。 2.用原码、反码和补码表示有符号整数,是在给定的机器字长下进行的,机器字长决定了补码的模。 下面对原码、反码、补码和真值加以总结。 1 原码、反码、补码是为解决负数表示而设计的规则,因此,正数的三种码是相同的。 (1)对于正数: 原码 =反码 =补码 (2)对于负数: 原码→反码:符号位不变,数值位逐位取反; 原码→补码:符号位不变,数值位逐位取反 +1(反码+1); 补码→原码:符号位不变,数值位逐位取反 +1(反码+1); 可以看出,原码与补码互为补码。 2 在某些情况下,需要从补码求真值或原码,其过程与求补码是相逆的,下面是补码求真值规则: (1)如果补码最高位是“0”,则将改为“+”号,数值不变; (2)如果补码的最高位是“1”,则将其改为“-”号,并将数值位的各位取反,然后最低位加1。 计算机高级语言定义的基本数据类型,通常使用补码表示有符号的整型变量,表2-3 列出了C语言中有符号整型变量的表示范围,这些范围就是补码表示范围。 【课程关联】高级编程语言 表2-3 C语言中有符号整数类型变量的表示范围 类型 范围 (signed)char -128——127 (signed) short -32768——32767 (signed ) int -32768——32767 -2147483648——2147483647 (signed) long -2147483648——2147483647 【例2-2】 试求出C语言中char型变量使用原码、反码和补码的表示范围。 解: 首先看真值,char型变量长度是8位,最小值是 -1111111,最大值是+1111111,则 原码 [-1111111]原 = 11111111 = -127 [+1111111]原 = 011111111 = +127 [+0 ]原= 00000000B [-0 ]原。= 10000000B 反码 [-1111111]反 = 10000000 = - 127 [+1111111]反 = 011111111 = +127 [+0 ]反= 00000000B [-0 ]反= 11111111B 补码 [-1111111]补 = 10000000= -128 [+1111111]补 = 011111111 = +127 [+0 ]补= 00000000B [-0 ]补= 00000000B,与[+0 ]补是同一个数。 由于原码和反码都存在+0和-0,而补码只有+0,所以补码范围较原码和反码要大1。 C语言中char型变量的真值、原码、反码和补码表示总结在表2-4中。可以看出,补码表示的范围最大。 表2-4 C语言中char型变量的真值、原码、反码和补码 二进制数码 数值(无符号位) 原码 反码 补码 00000000 0 +0 +0 +0 00000001 1 +1 +1 +1 00000010 2 +2 +2 +2 … … … … … 01111101 125 +125 +125 +125 01111110 126 +126 +126 +126 01111111 127 +127 +127 +127 10000000 128 -0 -127 -128 10000001 129 -1 -126 -127 10000010 130 -2 -125 -126 … … … … … 11111101 253 -125 -2 -3 11111110 254 -126 -1 -2 11111111 255 -127 -0 -1 【例2-3】 在8位字长计算机中,计算下面数的原码、补码和反码。 0,16 -16,+63,-63,+127,-127 解: [+0]原 = [+0]反 = 00000000B [-0]原 = 10000000B, [-0]反 = 11111111B [0]补 = 00000000B,补码不论+0和-0,它们是相同的。 [+16]原 =[+16]反 =[+16]补 = 00010000B [-16]原 =10010000B [-16]反 = 11101111B [-16]补 = 11110000B [+63]原 =[+63]反 =[+63]补 = 00111111B [-63原 =10111111B [-63]反 = 11000000B [-63]补 = 11000001B [+127]原 =[+127]反 =[+127]补 = 01111111B [-127]原 =11111111B [-127]反 = 10000000B [-127]补 = 10000001B 4.移码 移码又称为增码或偏码,常用于表示浮点数的阶码。 移码的规则是:不论正负数,移码都是将补码的符号位取反。 【例2-4】 在8位字长计算机中,若X = +101101B ,Y = -101101B ,求X和Y的移码 [X]移、[Y]补。 解:先求补码再求移码 [X]补 =00101101B,[X]移 =10101101B [Y]补 =100000000B – 101101B =11010011B [Y]移 =01010011B 2.2.2定点数表示 在计算机数值数据表示中,一般的实数(小数)可以采用两种表示方法:浮点数和定点数。 在实数表示中,正负符号位需要用一个二进制位来表示和存储,但小数点位置则可以事先约定而不必存储。根据实数表示中小数点的位置是固定的还是浮动的,有两种表示法:定点数和浮点数。在定点数中,小数点位置是事先固定下来的,不会变动,而在浮点数中,小数点位置是浮动的,随着所需表示数值的大小的不同,小数点位置可以变动。 采用定点数表示的计算机称为定点机,采用浮点数表示的计算机称为浮点机。定点机在数据使用上不够方便,不利于同时表达特别大的数或者特别小的数,但其结构简单、成本低,一般多见于低档微型计算机和单片机;而浮点机可以表示的范围比定点机要大得多,在数据使用上比较方便,但结构相对复杂、成本高,一般见于大、中型计算机以及高档微型计算机。有些计算机同时设计有定点和浮点处理器,分别支持定点和浮点运算。 下面从三个方面比较定点数和浮点数,在表示范围方面,同样字长下定点数可表示数值范围较小,而浮点数可表示的数值的范围较大;在数据处理上,定点数要求的计算处理硬件简单,而浮点数要求的计算处理硬件复杂;在相同条件下,一般浮点运算比定点运算速度慢。 在定点数表示中,通常有两种约定小数点固定位置的方法:整数表示法和纯小数表示法,在整数表示法中,小数点的位置隐藏在数值部分之后,而在纯小数表示法中,小数点隐藏在数值部分的最前面,如图2-1所示。 图2-1 定点数的两种表示方法 在应用定点数时要注意以下几个问题。 【注意】 (1)目前定点机大多采用定点纯整数表示法,因此,定点数表示的运算通常称为整数运算。 (2)对于一般的非纯小数运算,首先通过移动小数点位置化成整数或纯小数表示,然后再进行运算,在得到运算结果后还需将小数点位置反向移回来。 (3)在定点纯小数表示法中,如果表示的数过小,例如0.000…0001101,可用适当的比例因子将其化为0.1101后再用定点数表示,否则可能会超过计算机字长而产生溢出或损失精度。 (4)定点数与浮点数是从小数点位置考虑数值编码的,而原码、反码、补码与移码是从符号位考虑数值编码的,在定点和浮点数中都涉及到符号位,也会采用原码、反码、补码等表示方法。 【例2-5】 在8位字长计算机中,采用定点纯小数表示下面的数,并写出补码形式。 0.6875,-0.6875 解:首先将+0.6875D和-0.6875D化成二进制数,用真值表示,然后再计算补码。 0.6875 x 2 = 1.375 取1 0.375 x 2 =0.75 取0 0.75 x 2 =1.5 取1 0.5 x 2 =1.0 取1 +0.6875D = +0.1011B, -0.6875D = -0.1011B,两个数的数值部分一样, [+0.6875]补 = 0.1011000B = 0.1011B [-0.6875]补 = 1.0101000B = 1.0101B 【注意】定点小数计算时应注意以下问题: (1)小数点前的“0”代表符号+,“1”代表符号-,不再是整数部分的含义。 (2)末尾的0可以省略,对补码计算没有影响。 上例中,由于在8位机上计算,数值位是7位,[-0.6875]原=1.1011000,[-0.6875]反=1.0100111,反码最低位加1,得到[-0.6875]补=1.0101000B = 1.0101B。如果小数点最后的3个“0”省略,则按4个数值位计算,[-0.6875]原=1.1011,[-0.6875]反=1.0100,反码最低位加1,得到[-0.6875]补=1.0101。两次计算结果相同。 【例2-6】 在8位字长计算机中,写出下面数的两种定点数表示方法,并写出补码形式。 6.3125,-6.3125 解: 这两个数是非纯小数,既可以采用定点整数表示法,也可以采用定点纯小数表示法。 首先将两个数化为二进制数,并用真值表示。 整数部分6 = 110 小数部分 1010 0.3125 x 2 = 0.625 取0 0.625 x 2 =1.25 取1 0.25 x 2 =0.5 取0 0.5 x 2 =1.0 取1 所以,6.3125 = +110.0101B,-6.3125 = -110.0101B 如果采用定点整数表示法,需要将小数点向右移动4位。 6.3125整数形式的补码为01100101B, -6.3125整数形式的补码为10011011B。 如果采用定点纯小数表示法,需要将小数点向左移动3位 6.3125的纯小数形式的补码为0.1100101B, -6.3125纯小数形式的补码为1.0011011B。 2.2.3浮点数表示 用定点数表示整数或纯小数比较方便,但应用中常常需要处理非纯小数,这时用定点数表示就比较麻烦,特别是同时处理多个差异很大的数据,定点数就无能无力了。例如,电子的质量是9.019x10-31kg,太阳的质量是1.989x1030kg,要想同时表达这两个数量级相差特别大的数,即使利用64位定点数,其可区分的范围也只有1019,而用浮点数却能够很好地解决这个问题。因此,计算机高级语言通常使用浮点数来表示小数,例如C语言使用float类型和double类型数据表示不同精度和范围的小数。 数学上通常采用科学计数法表示较大范围的数值,科学计数法将一个数据表示成一个小数乘以一个以10为底的指数形式,其中,小数代表了这个数据的有效数字,而以10为底的指数代表了这个数据的范围,又称为比例因子。 科学计数法实现了有效位数和数据范围的分离,通过更改比例因子,将一般小数表达为纯小数,前面提到的电子和太阳质量就是用科学计数法表示的。 电子质量:9.019x10-31 = 0.9019x10-30,4个有效数字是9,0,1,9,数据范围是10-30。 太阳质量:1.989x1030 = 0.1989x1031,4个有效数字是1,9,8,9,数据范围是1031。 二进制浮点数也可以采用科学计数法表示。 N = 2E×M (式2-6) 其中,M称为浮点数的尾数,它是一个小数,表示有效数字的位数,决定了浮点数的表示精度;E称为浮点数的指数,或称为阶码,它是一个整数,表示小数点在数据中的位置,决定了浮点数的表示范围。 浮点数也有符号位,在二进制数据中,一个有符号位的浮点数,需要将符号位(1位),阶码(假设为m位)和尾数(假设n位)一并存储,共占用m+n+1个二进制位,如图2-2所示。 图2-2 浮点数的表示和存储 1.浮点数的规格化 对于同一个浮点数,当采用不同的阶码和尾数表示时,所得到的表示方式不唯一,例如1.25可以有如下多种形式: 1.25D= 1.01B = 1.01×20 = 0.101×21 (规格化形式) = 0.0101×22 = 0.00101×23 浮点数的规格化是指当浮点数的尾数不为0时,通过向左、向右移动小数点位置,同时修改阶码,使尾数最高有效位变成“1”,的形式,其中b取值0或1,在上面例子中,1.25D的规格化形式是0.101×20,而其他都是非规格化的形式。 将一个非规格化浮点数转换为规划化形式有两种操作: 向右规格化:当尾数最高有效位1位于小数点前面时,如,需要尾数右移若干位,变成规格化形式,同时阶码增加,尾数每右移一位,阶码增加1。 向左规格化:当尾数最高有效位1处于小数点后面若干位时,如,需要尾数左移若干位,变成规格化形式,同时阶码减少,尾数每左移一位,阶码减少1。 由于尾数域是有限的,尾数的向左、右规格化都会造成有效数据的移出与丢失,但是向右规格化丢失的是最低有效位,而向左规格化丢失的却是最高有效位。因此向右规格化更能减小数据误差。 浮点数规格化能够在尾数中保留最多有效数字,从而提高浮点数表示精度,还可以使浮点数表示具有唯一形式,便于统一存储。 2.IEEE-754标准浮点格式 由于同一个浮点数可以采用不同的表示方式,相应地,基数、尾数、阶码和符号位的表示和存储就会存在差别。在浮点数标准公布之前,各种计算机系统都采用各自的浮点表示和运算规则,导致采用浮点数运算的软件很难在不同计算机之间移植。为此,美国IEEE(Institute of Electrical and Electronic Engineers,国际电气和电子工程师协会)提出了IEEE-754标准(1985年),作为浮点数格式的国际统一标准,当今流行的计算机几乎都采用了这一标准,高级编程语言中的浮点表示也普遍遵循这一标准。 在IEEE-754标准中,规定一个浮点数N使用基数2,并且在逻辑上使用三元组{S,E,M}来表示,其中S为符号位,用0表示正,1表示负。 M为尾数,用原码表示,并采用如下规格化形式:尾数最高有效位为“1”(M非0时)。鉴于最高有效位为“1”,所以在尾数存储时,为节省存储量,只存储“1”之后的有效数字,也就是说,如果尾数存储的数值是M,而实际代表的数值是1.M,也就是实际有效位数比尾数M多1。 E是阶码,采用移码表示,移码表示的优点是可以保证阶码原有的大小顺序,并方便操作。实际存储阶码M时,需要将真实指数e加上一个偏移量bias,也就是说,如果存储的阶码是E,而实际指数e是E减去偏移量bias,即e = E-bias。 IEEE-754具体规定了两种浮点数格式:单精度浮点数用4个字节(32位)存储;双精度浮点数则用8字节(64位)存储,如图2-3所示。在C语言中,float型变量采用单精度浮点数表示,double型变量采用双精度浮点数表示。 图2-3 IEEE-754中单精度和双精度浮点数格式 在32位的单精度浮点数中,符号位S占1位,阶码占8位,偏移量bias是127(7FH),尾数M占23位,由于尾数隐藏小数点前的1位,实际有效位是24位,单精度浮点数的真值为 (-1)S 1.M 2E-127 e=E-127 (式2-7) 在64位的双精度浮点数中,符号位S占1位,阶码占11位,偏移量bias是1023(3FFH),尾数M占52位,由于尾数M隐藏小数点前的1位,实际有效位是53位,双精度浮点数真值为 (-1)S 1.M 2E-1023 e=E-1023 (式2-8) 下面以单精度浮点数为例,说明一些特殊值及其表示范围。 (1)机器0:下面两种情况都视为机器0,一种情况是尾数M为0,不管阶码E是何值;另一种情况是阶码E比它所能表示的最小值还小,不管尾位数M为何值。例如在式2-7中,如果1.M是0,或者E-127<-127 都被认为是机器0。 (2)+0和-0:当阶码E全为0且尾数M也全为0时,表示的真值为0,结合符号位S,则有+0和-0。 (3)+∞和-∞:当阶码E全为1且尾数M全为0时,表示的真值为无穷大,结合符号位S,则有正无穷大+∞和负无穷大-∞。 (4)阶码的表示范围:以单精度浮点数为例,除浮点数中的0和∞外,阶码E的取值只能是1~254,当减去偏移量127后,实际指数的范围变为-126~ 127,所有单精度浮点数的表示范围是2-126~2127≈10-38~1038。 3.浮点数精度的讨论 由于大部分十进制的小数无法精确转为二进制小数,在计算机内部采用浮点数进行科学计算时可能会产生误差,例如下面的C语言程序运行结果。 【课程关联】高级语言 #include int main(void){ float f1=34.6; float f2=34.5; float f3=34.0; printf("34.6-34.0=%f\n",f1-f3); printf("34.5-34.0=%f\n",f2-f3); return 0; } 运行结果为: 34.6-34.0=0.599998 34.5-34.0=0.500000 显然34.6-34.0=0.599998≠ 0.6,产生误差的原因是 34.6 无法精确地表达为单精度浮点数,类似地,程序中还会出现0.1+0.2 ≠ 0.3问题,所以程序设计中,要正确使用判断条件,在输出结果时也要合理采用四舍五入的方法。 【例2-7】假设由S,E,M三个域组成一个32位非零规格化浮点数x,其真值表示为(非IEEE 754标准): x=(-1)s×(1.M)×2E-128 其中S,E,M的存储格式与IEEE-754标准一致,问:它能表示的最大正数、最小正数、最大负数、最小负数各是多少? 解: 最大正数 0 1111 1111 111 1111 1111 1111 1111 1111 x=[1+(1-2-23)]×2127 最小正数 000 000 000000 000 000 000 000 000 000 00 x=1.0×2-128 最小负数 111 111 111111 111 111 111 111 111 111 11 x=-[1+(1-2-23)]×2127 最大负数 100 000 000000 000 000 000 000 000 000 00 x=-1.0×2-128 【例2-8】若浮点数x的754标准存储格式为41360000H,求其十进制数值。 解: 将十六进制数41360000H转换为二进制数 由x的存储格式可知,它是单精度浮点数,将16进制数展开后,可得二制数格式为 0 100 00010011 0110 0000 0000 0000 0000 B S E(8位) M(23位) IEEE-754标准使用1位符号位,8位阶码,23位尾数,因此可以分别提取这些内容 符号位S=0,表示正数 阶码E=10000010B= 130D, 则实际指数e = E-127 =130D-127D=3D 尾数M=1.011 0110 0000 0000 0000 0000B=1.011011B 包括隐藏位1的尾数 1.M=1.011011B 根据公式写出实际数值大小 x=(-1)S×1.M×2e=+(1.011011)×23= +1011.011B=11.375D 【例2-9】将20.59375D转换成754标准的单精度浮点格式。 解: 将十进制数转换为二进制数 20.59375D = 10100.10011B 规格化二进制数:移动小数点4位后,使其在第1,2位之间  10100.10011B = 1.010010011×24 实际指数e=4,1.M=1.010010011B 计算M、E、S M隐去小数点前的1,共9位,后补14个0得到23位的位数,即 M= 01001001100000000000000B E=4+127=+131D, 即E = 10000011B S=0 以32位浮点数格式表示该数 单精度浮点数的二进制存储格式为: 0 1000001 1 0100100 11000000 00000000B = 41A4C000H S E(8位) M(23位) 2.2.4十进制数的表示 虽然在计算机内部以二进制处理数据,但人们使用计算机时仍习惯以十进制数做为输入,以十进制数输出,因此需要将十进制数以二进制编码表示,下面说明几种编码方式。 (1)ASCII码串 十进制数用ASCII码字符串表示时,通常使用多个字节表示和存储,包括一个符号位字节以及一个或多个数值位字节,而每个字节都是ASCII码。 符号位用2BH表示正号“+”,用2DH表示负号“-”,数值位0~9则用30H~39H表示。 例如,+234用4个字节的ASCII码2BH 32H 33H 34H表示,其中符号位”+”用2BH表示,数值部分2,3,4分别用32H,33H,34H表示,类似地,-2345用5个字节的ASCII码2DH 32H 33H 34H35H表示,这种表示方法称为前分割数字。 此外还有后嵌入数字串表示方法,其特点是符号位不独占1个字节,而是和最低数值位放在一个字节中,具体规则是:如果符号位为正,则最低数值位不变;如果符号位为负,则最低数值位加上40H,例如+234表示为32H 33H 34H,-2345表示为32H,33H,34H,45H。嵌入数字串能够节省一个符号位字节,但不适合计算,一般用于非数值计算中。 (2)BCD码 BCD(Binary Code Decimal)码是二进制编码的十进制数,最常用的BCD码是8421-BCD码(简称8421码,又称压缩BCD码),其编码方法是用4位二进制数来表示1位十进制数的0~9,这4位的权从高位到低位依次为8、4、2、1,表2-5是8421-BCD码编码表。 表2-5是8421-BCD码编码表 十进制 8421-BCD (二进制) 十六进制 十进制 8421-BCD (二进制) 十六进制 0 0000 0 8 1000 8 1 0001 1 9 1001 9 2 0010 2 10 00010000 10 3 0011 3 11 00010001 11 4 0100 4 12 00010011 12 5 0101 5 13 00010011 13 6 0110 6 14 00010100 14 7 0111 7 15 00010101 15 压缩BCD码用4位二进制数表示1位十进制数,用1个字节表示2位十进制数,形成BCD串。按照此规则并参考表2-5可以得到,15的压缩BCD码是0001 0101B,即十六进制的15H;239的压缩BCD码是0010 0011 1001B,即十六进制的239H。 BCD码分为压缩BCD码和非压缩BCD码两种形式,通常所说的BCD码是指压缩BCD码。非压缩BCD码是用8位二进制数表示1位十进制数,即1个字节表示1位十进制数,并规定低4位表示0~9,而高4位全为0,例如29的非压缩BCD码表示为00000010B,00001001B,即十六进制的02H,09H。 相比ASCII码串,BCD码表示和存储多位十进制数更节省存储空间,而且一些计算机系统还提供了BCD码运算指令,支持BCD码直接运算,因此,BCD码应用更为广泛。 对于有符号的十进制数,可以用有符号位的BCD码表示。以压缩BCD码为例,通常是在其最高位之前增加半个字节表示符号位,0000B表示“+”号,0001表示“-”号,例如+56,用0000 0101 0110B表示,-56用0001 0101 0110B表示。 BCD码是一种有权值的十进制数编码,除此之外,还有无权值的编码,如余三码、格雷码等。 2.2.5 非数值数据的表示 非数值数据通常指字符、字符串、图形、图像、汉字等数据,下面主要介绍字符和汉字的编码方法。 字符的编码主要有ASCII编码以及Unicode编码,它们既用于表示字符,也用于表示字符串(字符序列)。 1.ASCII码 ASCII码是美国国家标准局(ANSI)制定的美国信息交换标准代码 (American Standard Code for Information Interchange,ASCII),是最为通用的单字节编码系统,主要用于显示现代英语字母和符号,已被国际化标准组织(ISO)定为国际标准,称为ISO/IEC 646,到目前为止共定义了128个字符。 ASCII码中的每个字符用1个字节来表示和存储, 其中用低7位的二进制编码(0~127)表示1个字符,总共可以表示128个字符,最高位固定为0。ASCII字符码表如表2-6所示,其中横轴表示7位中高3位二进制数b6、b5、b4,纵轴表示ASCII码7位中低4位二进制数b3、b2、b1、b0,括号中的数字为对应的十六进制数。为表达和书写方便,在表示一个ASCII字符时,也常常用十六进制数。例如,字符“A”的ASCII码可以写成01000001B,或41H。 表2-6 标准ASCII字符码表 b6b5b4 b3b2b1b0 000 (0) 001 (1) 010 (2) 011 (3) 100 (4) 101 (5) 110 (6) 111 (7) 0000 (0) NUL DLE SP 0 @ P ` P 0001 (1) SOH DC1 ! 1 A Q a q 0010 (2) STX DC2 " 2 B R b r 0011 (3) ETX DC3 # 3 C S c s 0100 (4) EOT DC4 $ 4 D T d t 0101 (5) ENQ NAK % 5 E U e u 0110 (6) ACK SYN & 6 F V f v 0111 (7) BEL ETB ' 7 G W g w 1000 (8) BS CAN ( 8 H X h x 1001 (9) HT EM ) 9 I Y i y 1010 (A) LF SUB * : J Z j z 1011 (B) VT ESC + ; K [ k { 1100 (C) FF FS , < L \ l | 1101 (D) CR GS - = M ] m } 1110 (E) SO RS . > N ^ n ~ 1111 (F) SI US / ? O _ o DEL ASCII码表的128个字符可以分为两类:可显示(可打印)字符和不可显示(不可打印)字符,或称控制字符。 可显示字符共95个,包括10 个十进制数字(0~9 )、52 个英文大写和小写字母(A~Z ,a~z )、以及若干个运算符和标点符号,其中, (1)数字符号0~9:按顺序排列,ASCII码分别对应30H~39H, (2)英文字母:排列顺序是大写字母在前,小写字母在后,大、小写字母均按顺序排列,例如字母“A”的ASCII码是41H,字母“B” ASCII码是42H,字母“a” ASCII码是61H。 不可显示的控制符号共33 个,早期用于控制计算机外围设备的某些工作特性,现在多数已被废弃。 ASCII码的字节最高位固定为0,称为标准ASCII码。在某些情况下,最高位还可作其他用途。例如,用作西文字符和汉字的区分标识,用作奇偶校验位以检验错误,一些公司还使用最高位进行编码扩展,因为让最高位为1,还可以多表示128个编码字符(128~255),这样ASCII码将最多表示256个字符,称为扩展ASCII码,但由于没有统一的标准,自行定义的扩展ASCII码之间是互不兼容的。 2.Unicode码 Unicode码是一种全新的编码,其设计目标是容纳全世界所有语言的全部字符,Unicode为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换和处理的要求。 为了表示更多的字符,必须增加更多的二进制位参与到编码中,常用的Unicode码是UCS-2(2-byte Universal Character Set,2 字节通用字符集),每个字符占用2个字节,使用16位的编码空间,理论上允许表示216=65536个字符,基本上满足了各种语言的使用需要。后来考虑到未来特殊应用和扩展的需求,人们又提出了UCS-4编码,每个字符占用4个字节。 【注意】Unicode仅仅只是字符集,其为每个字符都规定了用来表示该字符的二进制代码,但并没有规定二进制代码如何存储,要解决其存储问题需要用到UTF-8和UTF-16编码。 在计算机系统中ASCII字符只需要1个字节表示,UCS-2需要2个字节表示,UCS-4需要4个字节表示,那么在计算机系统中如何处理一个占用4字节的字符呢?计算机会将它认为是4个ASCII码,还是2个UCS-2,还是1个UCS-4呢?另外,如果将所有符号都用4字节表示显然会造成存储容量的浪费,所以在实际应用中采用了UTF-8和UTF-16编码规则。 UTF-8 是目前互联网上使用最广泛的一种 Unicode 编码方式,其最大特点就是可变长,使用1-4个字节表示一个字符,根据字符的不同而变换长度,从而实现了对 ASCII 码的向后兼容。UTF-16也是一种可变长的Unicode编码方式,其采用2个字节或4个字节表示一个字符。 综上,在计算机系统中,为了表示每个字符,扩展ASCII码用1字节,Unicode UCS-2字符集用2字节,Unicode UCS-4字符集用2字节位,而UTF-8编码使用1-4个字节表示,UTF-16编码使用2字节或4字节。 3. 汉字的编码方法 西文是一种拼音文字,使用若干有限字母就可以拼出所有的单词,因此编码规则简单,使用少量的字母和一些符号、标点等辅助字符就可以组成西文字符集,ASCII编码已能满足西文的应用需求。 中文的编码要复杂得多,中文信息的基本组成单位是汉字,汉字总数超过6万个,常用汉字也有7000个左右,数量庞大,还有简体、繁体的区别。而且,汉字的编码会涉及到计算机输入、内部处理以及计算机输出的全部过程,对应地,通常将汉字的编码分为输入码、交换码、机内码和字形输出码,如图2-4所示。在设计编码时,要为每个汉字设计一个编码,而且这些编码要与西文字符和其他字符有明显的区别。 图2-4 从输入到输出过程的汉字编码 (1)输入码 输入码是指从键盘输入汉字的编码,属于机外码,简称外码。一个汉字有多种不同的输入码,一个好的输入法应该是便于记忆,码长短,重码少。按照编码原理和规则,输入码主要分为4类:数字码、拼音码、形码和混合码。 数字码将待编码的汉字集以一定的规则排序,然后依次逐个赋予相应的数字串,以此作为汉字输入码,典型的数字码是区位码和电报码,用4个数字对一个汉字进行编码,由于编码难记忆,现在很少使用。拼音码以汉语拼音方案为基础而设计的编码,分为全拼输入法,双拼输入法等,最大优点是简单易学,是主流的汉字输入方法。字形码以汉字的形状为基础而确定的编码,把汉字的笔画或部件用字母或数字进行编码,常用有五笔字型码、郑码、表形码等,优点是码长较短,重码率低,输入速度快,但需要学习和记忆一些规则。混合码是将汉字的字形与字音相结合,也称为音形码或结合码,常用的有自然码等。 (2)交换码 交换码主要用于汉字信息处理系统或通信系统之间的信息交换,也称为汉字国标码。国家标准总局公布的国家标准GB2312-80,即《信息交换用汉字编码字符集-基本集》中共收集常用汉字6763个,其中一级汉字3755个(常用汉字),二级汉字3008个(次常用汉字)、加上682个图形符号共计7445个。 在GB2312-80中,全部汉字与图形符号组成一个94×94的矩阵,矩阵的每一行称为一个“区”,每一列称为一“位”,形成94个区(01~94区)、每个区内94位(01~94位)的汉字字符集。一个汉字所在区号和位号组合在一起就构成一个4位数的代码,前两位数字为“区码”(01~94),后两位数字为“位码”。一个汉字的区码和位码可以用2个字节表示,即1个字节区码和1个字节位码,这种汉字表示方式称为“区位码”。例如,汉字“啊”的区位码为1601(或表示为1001H),表示该汉字在16区的01位。 以区位码为基础,在区码与位码上分别加20H,就形成了国标码,即 国标码高位 = 区码+20H (式2-9) 国标码低位 = 位码+20H (式2-10) 汉字“ 啊” 的国标码为3021H ,加20H的原因主要是为了避免国标码与标准ASCII 码中的控制码发生冲突,在ASCII中控制码基本都集中在20H(空格)之前。 (3)机内码 机内码是在计算机内部对汉字信息进行各种加工、处理所使用的编码,简称内码。汉字可以通过不同的输入码输入汉字,但在计算机内部其内码是唯一的。当计算机系统中同时存在ASCII码和汉字国标码时,将会产生二义性,为了保证汉字处理系统中西文的兼容,就需要采用机内码。 例如:有两个字节的内容分别为30H和21H,它既可表示一个汉字“啊”的国标码(3021H),又可表示两个西文“0”和“!”的ASCII码(30H和21H),为此,汉字机内码应对国标码进行适当的处理和变换,考虑到标准ASCII码的最高位固定为0,只需将机内码的最高位规定为1即可,因此在国标码的高位和低位分别加上80H. 机内码高位 = 国标码高位+80H = (区码+20H)+80H = 区码+A0H(式2-11) 机内码低位 = 国标码低位+80H = (位码+20H)+80H = 位码+A0H (式2-12) 经过这样变换后,汉字“啊”的机内码为B0A1H,显然,其中每个字节B0H,A1H都容易与标准ASCII码区分开。 (4)字形输出码与汉字库 为了实现显示和打印汉字,需要将机汉字机内码转换为汉字可见的字形,这就是字形码。为此,首先需要在计算机内部存储每个汉字的字形码,每个汉字字形码在存储器中与其存储地址是一一对应的,当需要显示和打印输出汉字时,只要找到汉字的存储地址就可以取出存储的汉字字形码,并送至输出设备。根据构造和存储汉字字形方法的差别,汉字字库分为点阵字库和矢量字库。 点阵字库 点阵字库是计算机字库中字形信息的存储方式,用这种方式构造的字体,每个汉字字符包含m列和n行,用一个由m×n个像素组成的位图表示,这个m×n的点阵称为一个字模(Mask),点阵中的每个点都只有两种状态,即有笔画和无笔画,用二进制数字来表示,即1表示有笔画,对应像素应置为字符颜色;0表示无笔画,对应像素应置为背景颜色或不改变。 点阵字型库可分为低分辨率和高分辨率两大类,低分辨率用于一般的信息处理系统,如16×16点阵、24×24点阵、32×32点阵,而高分辨率用于印刷系统,一般需要在64×64点阵以上。 不同的点阵字模需要的存储容量是不同的,当表示一个汉字时,用16×16点阵需要16×16 =256位二进制数,即32字节存储,而用64×64点阵则需要64×64 = 4096位,即512字节存储。 如图2-5所示是汉字“英”的16×16点阵字形,在图中右侧列出了每一行像素的十六进制编码。 图2-5 汉字的字模点阵及其编码 一个汉字字库存储容量是每个汉字占用的存储量乘上汉字个数。一般地,汉字字库会为每个字符存储多种点阵字形,以及多种字体的字形,所以字库存储空间比较大,多数汉字信息处理系统将汉字字库存储在硬盘上,使用专门的软件完成从汉字内码到汉字字模点阵的转换,这样的字库称为“软字库”。此外,一些外设(如打印机)或嵌入式计算机将汉字字模点阵固化在只读存储器芯片内部,称为“硬字库”,以方便汉字字模存取。 矢量字库 点阵字库存取字形速度快,但缩放后的字形质量难以保证,字体放大后可能出现边缘锯齿或笔画损失,影响字体的美观。相比之下,矢量字库中存储的是不同字体文字的外部形态的矢量信息,计算机可根据字号改变矢量值,并根据轮廓充填而形成文字。 矢量字库保存的是每一个汉字的描述信息,比如一个笔画的起始坐标、终止坐标、半径、弧度等等,只需要改变缩放系数即可改变文字的字号。汉字字形是通过数学曲线来描述的,包含了字形边界上的关键点、连线的导数信息等,在显示、打印这一类字库时,要经过一系列的数学运算才能输出结果,这样产生的字体可以无限放大而不产生变形。Windows操作系统中使用的TrueType字体就是属于矢量字体库。 (5)汉字编码的发展 我国使用的计算机汉字操作平台中常见有如下几种汉字字符集:GB2312 字符集、GB12345字符集、BIG5字符集、GBK字符集、GB18030字符集以及GB2312 字符集。 GB2312字符集即国标码字符集GB2312-80,全称《信息交换用汉字编码字符集-基本集》。其由中国国家标准总局发布并于1981年5月1日起实施,是中国国家标准的简体中文字符集,其所收录的汉字已经覆盖99.75%的使用频率,基本满足了汉字的计算机处理需要。 GB12345-90字符集是国家标准总局1990年颁布的繁体字编码标准,全称为《信息交换用汉字编码字符集-第一辅助集》,共收录6866个汉字(比GB2312多103个字),纯繁体的字大概有2200余个。 BIG5 字符集又称大五码,1984年由中国台湾财团法人信息工业策进会和五家软件公司宏碁(Acer)、神通(MiTAC)、佳佳、零壹(Zero One)、大众(FIC)创立,故称大五码,共收录13053个中文字,该字符集主要在中国台湾地区使用。 GBK字符集是1995年底推出的中文编码扩展国家标准,兼容GB2312,共收录汉字21003个、符号883个,并提供1894个造字码位,简、繁体字融于一库,主要扩展了对繁体中文字的支持。 GB18030全称《信息技术 中文编码字符集》,它是由中华人民共和国国家标准所规定的变长多字节字符集。 其首个标准GB18030-2000于2000年3月17日发布,解决了汉字、日文假名、朝鲜语和中国少数民族文字组成的大字符集计算机编码问题,采用单字节、双字节和四字节三种编码方式,字符总编码空间超过150万个编码位,收录了27484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字,能满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。它与Unicode 3.0版本兼容,并与以前的国家字符编码标准兼容。 GB18030-2005于2005年11月8日发布,更新至Unicode 3.1中日韩统一表意文字(即扩展B区),并刊载少数民族包括朝鲜文、蒙古文(包括满文、托忒文、锡伯文、阿礼嘎礼文)、德宏傣文、藏文、维吾尔文/哈萨克文/柯尔克兹文和彝文的文字,收录了70,244个汉字。 GB18030-2022于2022年7月19日发布,收录了87887个汉字、228个汉字部首,在汉字数量上比2005版增加了1.7万余个生僻汉字,基本满足了人名、地名生僻字和古籍、科技用字的信息化处理需要。 2.2.6 数据的宽度和存储顺序 计算机内部的各种数据都需要采用二进制表示和存储,由于各种数据类型宽度与存储单元宽度不同,一个类型的数据常常会占多个存储单元,这就涉及数据在计算机内部存储顺序问题,本节主要讨论这个问题,至于两个或多个数据之间的存储顺序,属于数据结构课程中讨论内容。 【课程关联】数据结构 1.数据的宽度和单位 计算机中常用以下三种不同宽度数据单位。 (1)位 二进制数的最小单位是比特(bit),或称为“位元”,简称“位”,一位取值为0或者1。 (2)字节 字节(Byte)是计算机存储器容量的一种计量单位,1个字节=8位,计算中通常使用字节为单位表示编码,例如每个西文字符用1个字节表示,每个汉字用2个字节表示等,在用字节表示数据时,通常写成16进制形式。 (3)字长 字长是指CPU一次能够同时处理二进制数据的位数,字长是表示计算机性能的重要指标(1.4节),字长越长,数据表示范围就越大,精度也越高。通常所称的32位机和64位机,就是指计算机字长是32位和64位。 2.数据存储和排列顺序 (1)LSB和MSB 计算机内部存储的二进制数据是一串0,1组成的序列,每8位组成一个字节,不同数据类型具有不同的宽度,许多数据类型需要用多个字节表示。例如short数据宽度为两字节,int和float宽度为4字节,double型数据宽度为8字节等,这些数据类型表示中就有高字节和低字节之分,通常将最低的那个字节称为最低有效字节,用LSB(Least Signiticatnt Byte)表示,将最高的那个字节称为最高有效字节,用MSB(Most Signiticatnt Byte)表示。例如一个数值“6”,用int类型表示时需要用4个字节,用0,1序列表示为“0000 0000 0000 0000 0000 0000 0000 0110”,用16进制表示为“00H 00H 00H 06H”,其中MSB =00H,LSB =06H。 (2)数据存储地址 现代计算机中的主存大都采用字节编址方式(1.2.2),对主存空间的存储单元进行编址时,每个地址存放一个字节数据。例如int型数据“6”需用4个字节表示,那么在计算机主存中需要为它分配连续4个字节的存储单元,假设4个字节地址为1000H,1001H,1002H,1003H,则将最低地址定义为该数据的地址,即数据“6“的地址为1000H。 (3)两种存储顺序 如上所述,为了存储int型数据“6”,在计算机主存中连续分配4个字节,那么在1000H单元中存放“6”的LSB还是MSB呢?这就涉及到两种存储顺序:大端方式和小端方式。 大端(big endia)方式,将数据最高有效位MSB存放在最低地址单元中,将最低有效位LSB存放在最高地址单元中,这种方式也称为MSB优先方式,如图2-6(a)所示,最低地址单元1000H中存放的是“6”的最高有效位,即00H。IBM System 360/370,Motorola 68000, MIPS,HP PA等机器采用大端方式。 小端(little endia)方式,将数据最高有效位MSB存放在最高地址单元中,将最低有效位LSB存放在最低地址单元中,这种方式也称为LSB优先方式,如图2-6(b)所示,最低地址单元1000H中存放的是“6”的最低有效位,即06H。Intel 80x86,DEC,VAX等机器采用小端方式。 图2-6 数据存储的两种顺序 3.字符串的存储顺序 字符串是由多个字符(如ASCII 字符)组成的序列,每个ASCII字符用一个字节长度存储,如果计算机字长为32位,即4个字节,则字符串中每4个字符用一个字长度存储,而该字中各字符的存储顺序也有大端和小端两种不同方式。 2.3 数据的校验 数据在计算机内部进行存取、传送过程中,由于元器件的故障或者噪声干扰等原因会出现差错,为了减少和避免这种差错,除了提高计算机硬件可靠性,增加抗干扰能力外,还需要采取一定措施对数据本身进行正误验证,以便发现错误,或者纠正错误。 数据校验方法大多数基于“冗余校验”思想,除了原始有效数据外,还增加若干位编码,这些新增的编码称为校验位。 2.3.1 奇偶校验 1.奇偶校验的概念 奇偶校验是在若干有效数据位(例如1个字节)后加上1位的校验位,也称为校验码,使得数据整体(有效数据位加校验位)中“1”的个数成为奇数,或者偶数,由此,奇偶校验分成奇校验和偶校验两种校验规则,如图2-7所示。 图2-7 奇偶校验码 奇校验:如果有效数据位中1的个数为奇数,则校验位为0,否则为1,从而保证数据整体中1的个数为奇数。 偶校验:如果有效数据位中1的个数为偶数,则校验位为0,否则为1,从而保证数据整体中1的个数为偶数。 表2-7所示是奇偶校验例子,可见,校验位取值0或1是由数据位中1的个数决定的。 表2-7 一组奇偶校验的例子 数 据 1的个数 偶校验编码 奇校验编码 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 3 0 7 8 1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 根据奇校验的定义,不管有效数据位为多少,奇校验都不会出现整体数据各位为全0的情况,因此在实际应用中多采用奇校验。 奇偶校验是一种简单且应用广泛的数据校验码,可以检测出1位或奇数位的错误,但不能确定出错的位置,也不能检查出偶数位的错误。换句话说,奇偶校验发现差错的充分必要条件是有效数据中有1位或奇数位错误,在实际应用中,由于一位出错的概率要远远大于多位出错的概率,因此,奇偶校验是一种非常有效的校验方法。在存储器的数据检查中常常使用奇偶校验,在ASCII传送中也会经常将最高位作为奇偶校验位。 另外,从传送位置看,奇偶校验位可以约定放在有效数据位之后,也可以放在有效数据位之前。 2.奇偶校验的逻辑实现 奇偶校验易于用硬件逻辑电路实现,使用简单的异或电路就可以实现奇偶校验,以向主存中写入和读出一个带有校验码的字节为例,说明生成校验码和验证校验码两个过程。 (1)使用奇偶校验逻辑生成奇偶校验码 当将1个字节的代码D7~D0写主存时,先将它们送往奇偶校验电路,该电路将产生1位奇偶校验码,然后将8位数据和1位校验码一并写入主存。 生成奇校验码:当D7~D0中有奇数个1时,下面逻辑将使得奇校验位0,否则为1,即 奇校验位 = (式2-13) 生成偶校验码:当D7~D0中有偶数个1时,下面逻辑将使得偶校验位0,否则为1,即 偶校验位 = (式2-14) (2)使用奇偶校验逻辑发现奇偶校错误 当从主存读出数据时,将读出的9位代码(8位信息和1位校验码)同时送入奇偶校验电路进行校验。 奇校出错 = (式2-15) 偶校出错 = (式2-16) 如果奇校出错或偶校出错 = 1,则9位代码中有1位出错,包含奇偶校验位出错,但不能确定具体错误位置;如果奇校出错或偶校出错 = 0,则数据没有错误。 3.交叉奇偶校验 奇偶校验位可以看做是在数据横向上增加的校验位,如果在数据纵向也增加1个校验位,便形成纵横交叉奇偶校验,则可以发现2位错误,或者发现1位错误及其位置,交叉奇偶校验是一种增强型的奇偶校验方法。 在计算机内部进行大批量字节传送时可以采用交叉奇偶校验位,除了每个字节横向上的校验位外,还为多个字节组成纵向上的校验位。 表2-8 交叉奇偶校验   D7 D6 D5 D4 D3 D2 D1 D0 横向校验位 第1字节 1 1 0 0 1 0 1 1 1 第2字节 0 1 0 1 1 1 0 0 0 第3字节 1 0 0 1 1 0 1 0 0 第4字节 1 0 0 1 0 1 0 1 0 纵向校验位 1 0 0 1 1 0 0 0 表2-8的交叉奇偶校验在两个方向上均采用了偶校验方式,下面分析2位出错以及1位出错情况。假设第1个字节的D2,D3两位均出错,则横向校验位无法发现错误,但是D2,D3所在的纵向校验位却可以发现错误,因此这种校验能发现2位出错;假设只有第1个字节的D2出错,则横向可以检测出错误,纵向也可以检测出错误,因此这种校验不仅能发现1位出错,还能确定出错位置,从而进行纠正。 基于纵横交叉校验的原理,还可以构造更多的数据校验算法。例如Flash存储器的ECC(Error Checking and Correction)校验是一种用于差错检测和修正的算法。ECC校验每次对256字节的数据进行操作,包含列校验和行校验。这样的结构比上述4个字节的交叉校验更节省校验位占用的存储量。ECC能纠正1位错误和检测2位错误,而且计算速度很快,但对1位以上的错误无法纠正,对2位以上的错误不保证能检测,更多关于ECC的详细校验方法,请参看相关资料。 2.3.2 海明校验* 奇偶校验是在若干有效位之外加上1个校验位,可以检测出1位或奇数位的错误,但不能纠错,海明校验在基本奇偶校验基础上,采用多重奇偶校验方式,增强了数据校验能力,能够检测出1位或多位错误,并且在发生1位错误时能予以纠正。 假定有效数据D的位数为n,校验码P的位数为k,那么,校验码位数k应取多少呢?k位理论上能表示2k种状态,考虑只有1位错误的情况,实际错误有n+k种,即n位有效数据中某位有误,或者k位校验码中某位有误,再加上1种无错情况,实际状态共1+n+k种,这些状态应能被2k种状态表示,所以应满足条件 (式2-17) 例如,当n = 8,k至少为4,数据总位数是8+4=12,实际状态是13种(12种1位错误,1种无误),根据4位校验码的16种组合状态,就可以区分这13种情况,并检查出12种错误。类似地,当n = 4,k至少为3,数据总位数是4+3=7,实际状态是8种(7种1位错误,1种无误),根据3位校验码的8种组合状态,就可以区分这8种情况,并检查出7种错误。 在实际应用中,发送方首先计算有效数据D的校验码P,然后将n+k位数据整体发送出去;接收方接收到n+k位数据后,首先计算校验码P’,然后将其与接收到的P做异或运算得到故障字,最后根据故障字进行纠错。下面以n=4,k=3为例介绍纠错过程,这里只考虑1位错误,并采用偶校验方式。 首先将4个有效数据位分别记为D1,D2,D3,D4,3个校验位分别记为P1,P2,P3,由这7位组成信息位M1,…,M7。为了计算方便,信息位并不是将有效数据位和校验位顺序排列,而是“穿插”排列。为了清楚其排列方式,从3个校验位8种组合状态(S3 S2 S1)看,设S3 S2 S1= 000代表无错,在剩下的7种错误中,3种组合状态(001,010,100)只有一位“1”,令其分别代表每个校验位错误。由此将P1,P2,P3安排在M1,M2,M4位上(M1对应001,M2对应010,M4对应100),然后,将D1,D2,D3,D4安排在剩余的位置M3,M5,M6,M7上,这样得到的7位信息排列是:P1 P2 D1 P3 D2 D3 D4,如表2-9左边所示。 表2-9 海明校验校验码和故障字对应关系 M1 M2 M3 M4 M5 M6 M7 状 态 无误 7种错误 P1 P2 D1 P3 D2 D3 D4 0 1 2 3 4 5 6 7 组3 0 0 0 1 1 1 1 S3 0 0 0 0 1 1 1 1 组2 0 1 1 0 0 1 1 S2 0 0 1 1 0 0 1 1 组1 1 0 1 0 1 0 1 S1 0 1 0 1 0 1 0 1 接下来还要确定P1,P2,P3分别用哪些有效数据位计算校验码,我们将表2-9右边错误状态1~7所对应的三行编码值,分别复制到表左边M1~M7对应的三组1~3中,其中,对应“1”的信息位参与校验,对应0的信息位不参与校验,即 M1 = 0 M2 =0 M4 =0 表中M1,M2,M4分别对应P1,P2,P3,因此P1,P2,P3的表达式为 P1= = P2 = = P3= = 最后再看一下故障字的计算。接收方得到信息位M1~M7时,利用上述公式重新计算校验码,得到P1’、P2’和P3’,然后再计算故障字 S1 = P1P1’, S2 = P2P2’; S3= P2P2’ 故障字8种状态与表2-8中7种错误情况及1种无错情况对应,具体分三种情况处理: (1)如果S3 S2 S1均为0,则无误; (2)如果S3 S2 S1中有1位等于1,其他两位等于0,则是校验码出错,无需纠错; (3)如果S3 S2 S1中有2位或以上位等于1,则是有效数据位错误,在表中可以找出对应的有效数据位,并将其从1纠正为0,或从0纠正为1。 【例2-10】设4个有效数据位分别是1100,试计算校验码,如果有效数据在传输过程中发生了一位错误,从1100变成了0100,写出其纠错过程。 解:确定校验位的位数: 由公式可知,至少需要3位校验位,记为P1,P2,P3。有效数据位记为D1 D2 D3 D4 = 1100,它们构成信息为M1~M7(P1 P2 D1 P3 D2 D3 D4) P1= =1 P2 = P3= 发送端:将有效数据D1 D2 D3 D4 以及 P1 P2 P3作为整体发送出去。 接收端:接收到D1 D2 D3 D4 以及 P1 P2 P3,重新计算校验码,并根据故障字纠错。由于D1 D2 D3 D4 = 0100,故 P1’= 0 P2’= 0 P3’= 1 = 1 故障字S1 = P1P1’= 1, S2 = P2P2’= 1; S3= P2P2’= 0 由于S3 S2 S1 = 0 1 1,故知道M3即D1错误,因此,将D1从0纠正为1,最后得到正确数据1100。 上述纠正一位错误的海明校验称为单纠错码(SEC),此外,还有同时发现两位错误并纠正的海明校验(DEC-DED)。 由于海明校验主要采用异或运算,因此它易于硬件实现,具有广泛应用。 2.3.3 循环冗余校验 循环冗余校验(Cyclic Redundancy Check,CRC)是一种能够实现数据校验及数据纠错的校验码,通常用于网络传输的数据包和计算机文件的校验,例如辅助存储器数据校验。前面介绍的基本奇偶校验和海明校验方法都采用奇偶校验原理,用于校验或纠正信息中1位或2位错误,而CRC则利用除法及余数原理,能够发现并纠正信息中连续出现的多位错误,具有纠错比例高、执行速度快,使用灵活等特点。 假定有效数据的位数为n,首先将其表达为多项式M(x),然后将M(x)左移k位后再除以一个约定的生成多项式G(x),G(x)对应一个k+1位的二进制数,则得到的余数多项式R(x)将对应k位的校验码。将n个有效位以及k个校验位形成的n+k个位一起传输,称为循环校验码--(n+k,k)码,如图2-8所示。 在接收端,将收到的有效数据和校验位除以约定的生成多项式,如果余数为0,则没有发生错误,如果余数不为0,则表示发生了错误,由于错误位置不同,余数则不同,从而可以利用对应关系实现数据纠错。 图2-8 CRC(n+k,k) 假设6位有效数据是100011,多项式是M(x)=x5+x+1,约定的生成多项式为G(x)= x3+1,即4位数据 1001,利用模2多项式除法,得到3位校验码是111,称为CRC(10,3)码。 在接收到CRC码并校验时,将CRC码做同样计算,如果余数为0,则说明无错误;如果余数不为0,则说明发生错误。 选择生成多项式时需要考虑一定约束条件,并不是所有多项式都可以作为生成多项式。例如,要求任何一位发生错误时,余数都应该不为0,不同位发生错误时,余数应该不同等。CRC校验中采用的生成多项式有多种不同形式,对应的CRC校验也有不同的类别,常用CRC校验有CRC-16,CRC-32等版本,它们具有不同的校验和纠错能力。 循环冗余码具有纠错比例高的特点,能够检测出所有长度小于或等于校验位长度的突发错误,由于涉及的数学关系比较复杂,证明过程请参看相关书籍。 循环冗余码使用方式灵活,在网络应用中,有效数据由上千二进制位构成一帧数据,通常做法是只将CRC用于检测错误而不纠错,当接收方发现错误后通知发送方重新发送。因此,接收方只需用约定生成多项式进行模2除并判断余数是否为0,执行速度更快。 循环冗余码计算采用模2多项式除法,软件和硬件实现都比较简单,其硬件实现电路主要由异或和移位运算电路组成,可以实现数据快速校验。 2.4 定点运算和定点运算器 计算机中的基本运算分为两大类:算术运算和逻辑运算。 算术运算主要是指加、减、乘、除四则运算,其参与运算的操作数一般是有符号数,由于数值数据有定点表示和浮点表示,因此,有符号数的四则运算分为定点运算和浮点运算。 逻辑运算包括逻辑与、或、非、异或等运算,参与逻辑运算的操作数一般是无符号数。 本节先讨论运算方法,然后讨论执行运算任务的运算器的基本结构和工作原理。 2.4.1 定点数加、减法运算 计算机中的定点数有三种编码形式:原码、反码和补码,原则上三种编码的操作数都可以进行加、减法运算,但其操作的便捷性和难易程度不同,在2.1.1讨论过,补码的加、减法运算最为便捷,因此,现代计算机的定点运算器大都使用补码进行加、减法运算。 为方便起见,下面示例中的运算默认在8位计算机上进行,如果计算结果超过8位,就需要将超出的进位或借位舍弃,保留8位数(包括符号位在内),其运算规则也适合于其他字长的计算机;数据表示默认使用二进制,省略后缀B。 1.补码加法 补码加法的公式是 [x+y]补=[x]补+[y]补 (mod2) (式2-18) 式2-18是补码加法的理论基础,其含义是,两个数补码之和等于这两数之和的补码。其中模2是指参与运算的两个数的每一位都按二进制运算。 根据补码加法原理,两个真值数x,y求和的计算步骤如下: (1) 将真值x,y转换为补码,真值转换为补码的方法见2.2.1。 (2) 两个补码相加,得到的结果是和的补码。 (3) 将和的补码转换为真值。补码转换为真值是真值转换为补码的逆过程,计算方法相似。 【例2-11】 已知x = 0.1001,y=0.0011,求x+y 解: [x]补=0.1001, [y]补=0.0011 [x]补 0.1001 + [y]补 0.0011 [x+y]补 0.1100 (mod 2) 因为[x+y]补 =0.1001,所以x+y =0.1100 例2-11中给出的x,y是纯小数,因此x,y均采用纯小数的定点数表示,需要【注意】以下两个问题。 (1)真值和补码看上去都是小数,但是小数点前边0的含义不同,真值表示数值整数部分是0,而补码则表示数值符号位是“+”。 (2) 在8位字长计算机中,[x]补的完整形式是0.010100,即用1个符号位和7个数值位表示,由于小数点后边的0可以省略,所以也可以用0.0101表示。 【例2-12】 已知x = 0.1001,y= -0.0100,求x+y 解: [x]补=0.1001, [y]原= 1.0100,[y]补= 1.1100 [x]补 0.1001 + [y]补 1.1100 [x+y]补 10.0101 (mod 2) 将计算结果中最高位(符号位)产生的进位舍弃,则得到[x+y]补 =0.0101,然后转换为真值,所以x+y = 0.0101。 【例2-13】 已知x = -0.1001,y= 0.0100,求x+y 解: [x]原=1.1001, [x]补=1.0111 ,[y]补= 0.0100 [x]补 1.0111 + [y]补 0.0100 [x+y]补 1.1011 (mod 2) 因为[x+y]补 =1.1011,所以x+y = -0.0101 2.补码减法 按照代数加、减法规则,减去一个数等于加上这个数的相反数,所以 [x-y]补=[x+(-y)]补=[x]补+[-y]补 (mod 2) (式2-19) 一个数减去另一个数的补码,等于加上这个数相反数的补码,其中由y计算[-y]补可以采用以下两种方法。 (1)由真值求,先求出-y的真值,再转换为[-y]补; (2)由补码求,先由真值y求出[y]补,再求出[-y]补。从[y]补求出[-y]补的方法,即求补码的相反数规则:符号位取反,数值位取反加1 【例2-14】 已知x = 0.1001,y=0.0110,求x-y 解: [x]补=0.1001, -y = -0.0110 [-y]补= 1.1010, 还可以这样求[-y]补,先计算 [y]补= 0.0110,再得到 [-y]补= 1.1010, [x]补 0.1001 + [y]补 1.1010 [x+y]补 10.0011 (mod 2) 因为[x+y]补 =0.0011,所以x+y =0.0011 【例2-15】 已知x = -0.1001,y= 0.0110,求x-y 解: [x]补=1.0111, -y = -0.0110 [-y]补= 1.1010, [x]补 1.0111 + [y]补 1.1010 [x+y]补 11.0001 (mod 2) 因为[x+y]补 =1.0001,所以x+y =-0.1111 3.加法的溢出问题 在计算机数值表示中,由于计算机字长是有限的,如果运算结果超出计算机字长表示的范围,就会发生溢出,溢出会导致计算结果出错,所以必须对计算结果的溢出情况作出正确判断。在采用补码表示数据时,溢出是指计算结果超出了补码表示的范围,例如,在8位字长的计算机中,补码表示的范围是-128~127,如果运算结果大于补码表示的最大数127,则称为正溢出或向上溢出,如果运算结果小于补码表示的最小数-128,则称为负溢出或向下溢出。 在定点数加法中,可以根据运算结果中符号位及最高有效位产生进位的情况来判断结果是否发生溢出,具体分为单符号位法和双符号位法。 1.单符号位法 两个补码相加发生溢出的直观判断规则是: (1)如果一个为正数,另有一个为负数,则相加的结果不会发生溢出; (2)如果两个数都是正数,相加的结果却为负数,则发生了正溢出; (3)如果两个数都是负数,相加的结果却为正数,则发生了负溢出。 根据上述判断规则,利用符号位的进位位Cf以及最高有效位(最高数值位)的进位位C0 的关系得到如下溢出判断规则,其中产生进位记为1,未产生进位记为0: (1) 如果Cf与C0相同则表示没有发生溢出; (2) 如果Cf与C0不相同,则表示发生了溢出,如果Cf为0则是正溢出;如果Cf为1则是负溢出,如下表2-10所示。 表2-10 单符号位法判断溢出规则 Cf C0 溢出情况 0 0 没有发生溢出 0 1 发生正溢出 1 0 发生负溢出 1 1 没有发生溢出 表2-9的判断规则可以采用异或电路实现,输入端为Cf和CO,输出端为V,根据输出V=Cf ⊕ C0 即可判断是否发生溢出:如果V=0则没有发生溢出,如果V=1则发生了溢出。 【例2-16】 已知x = 0.1100,y= 0.1010,求x+y 解: [x]补=0.1100, [y]补= 0.1010 [x]补 0.1100 + [y]补 0.1010 [x+y]补 1.0110 (mod 2) 因为[x+y]补 =1.0110,符号位未产生进位即Cf =0,最高数值位产生进位即C0= 1,所以发生了溢出,又因为Cf =0,所以是正溢出。 【例2-17】 已知x = -0.1110,y= -0.1111,求x+y 解: [x]补=1.0010, [y]补= 1.0001 [x]补 1.0010 + [y]补 1.0001 [x+y]补 10.0011 (mod 2) 因为[x+y]补 =10.0011,符号位产生进位即Cf =1,最高数值位未产生进位即C0= 0,所以发生了溢出,又因为Cf =1,所以是负溢出。 【例2-18】 已知x = 0.1110,y= -0.1111,求x+y 解: [x]补=0.1110, [y]补= 1.0001 [x]补 0.1110 + [y]补 1.0001 [x+y]补 1.1111 (mod 2) 因为[x+y]补 =1.1111,符号位未产生进位即Cf= 0,最高数值位相加未产出进位即C0= 0,所以没有发生溢出,得到x+y = -0.0001。 2.双符号位法 双符号位法指将参与运算的两个补码的符号位重复一遍,然后再做加、减,最后根据运算结果中符号位判断是否发生溢出,规则如下: (1)运算结果的两个符号位一致,即均为11,或00,则没有发生溢出; (2)运算结果的两个符号位不一致,即为10或01,则发生了溢出,进一步,如果两个符号位为01则是正溢出,为10则是负溢出。不论是否发生溢出,最高符号位(即双符号位中左边的符号位)始终指示正确的符号,如表2-11所示。 【注意】在用双符号位法做加、减运算时,如果运算结果中的最高符号位也产生了进位位,则应该舍弃。 表2-11 双符号位法判断溢出 双符号位高位 双符号位低位 溢出情况 0 0 没有发生溢出 0 1 发生正溢出 1 0 发生负溢出 1 1 没有发生溢出 与单符号位相似,双符号位法也可以采用异或电路来判断是否发生溢出,这时异或电路的两个输入端是这两个符号位,输出端则为两个输入端的异或结果,如果输出端为0,则没有发生溢出,如果输出端为1则发生了溢出。 【例2-19】 已知x = 0.1100,y= -0.1010,利用双符号位法计算x-y 解: [x]补=00.1100, [-y]补= 00.1010 [x]补 00.1100 + [y]补 00.1010 [x+y]补 01.1110 (mod 4) 因为[x+y]补 =01.1110,结果中双符号为01,不同号,表示发生了溢出,并且为正溢出,计算结束。 【例2-20】已知x = 0.1110,y= -0.1111,用双符号位法求x+y。 解: [x]补= 00.1110, [y]补= 11.0001 [x]补 00.1110 + [y]补 11.0001 [x+y]补 11.1111 (mod 2) 因为[x+y]补 =11.1111,结果中的双符号为11,同号,表示没有发生溢出,接着需要将结果转化为真值,结果补码是[x+y]补 =1.1111,真值是x+y= -0.0001。 【例2-21】已知x = 0.1101,y= -0.1011,用双符号位法求x+y 解: [x]补=00.1101, [y]补= 11.0101 [x]补 00.1101 + [y]补 11.0101 [x+y]补 100.0010 (mod 2) 1舍弃 因为[x+y]补 =00.0010,结果中双符号00,同号,表示没有发生溢出,接下需要将结果转化为真值,结果补码是[x+y]补 =0.0010,真值是x+y= + 0.0010。 2.4.2. 定点乘、除法运算 运算器的基本功能是执行数据的传送、加法和移位运算,但实际应用中乘除法运算又常常是必不可少的,一般在计算机中采用如下方式实现乘、除法运算。 (1)采用软件实现乘除法运算。由于乘、除法运算可以用加、减法和移位运算,因此可以用软件实现乘、除法运算,并写成子程序供其他程序调用,这种方法无需增加新的硬件,但计算速度比较慢。 (2)采用硬件实现乘除法运算。在原有基本运算器电路基础上,增加左右移位和计数器等逻辑电路,同时增加专门的乘、除法指令来实现乘除法运算,这种方式的速度较第一种方式快。 (3)采用并行乘除法器。采用并行运算的乘除法器,例如高速的单元阵列乘除法器可以实现流水式阵列乘除法运算,这种方式的运算速度最快,但硬件成本也较大。 下面简要说明如何采用软件实现乘法运算。由于乘除结果的符号位容易确定,而运算结果的绝对值和参加运算数据的符号无关,所以用原码实现乘法比较简单。原码乘法运算转换为数值位的加法和移位运算,而符号位则根据乘法运算规则,如果相乘的两个数同号则结果为正,异号则结果为负。 【例2-22】 已知x = 0.1101,y= -0.1011,计算xy。 解: [x]原=0.1101, [y]原= 1.1011 [x]原 0.1101 x [y]原 1.1011 0.1101 0.1101 0.0000 0.1101 0.10001111 由于是两个异号数相乘,因此结果应该是负数,即-0.10001111。 如果考虑计算机字长为8位,则应该对上述结果进行舍入,采用0舍1入的方式,最终结果为-0.1001000。 在现代计算机中,由于加、减法采用补码运算,如果乘、除法采用原码运算,则在一般四则混合运算中需要进行原码和补码的转换,所以乘除法一般还是采用补码运算。补码乘法运算有多种方法,例如,根据每次部分积是一位相乘得到还是两位乘得到的,有补码一位乘法和补码两位乘法,另外布斯(Booth)乘法可以将符号位与数值位一起参与运算,直接得到补码表示的乘积,适合于正负数的运算。 2.4.3 逻辑运算 除了四则运算外,运算器还具备逻辑运算功能,逻辑运算主要包括逻辑与、或、非、异或,运算对象是无符整数。 由于二进制中的符号“1”和“0”分别与逻辑命题的“真”、“假”相对应,逻辑运算更为简便。 1.逻辑非运算 逻辑非运算(NOT)又称为取反运算,其运算规则是对某个操作数的各位按位取反,使每一位由0变成1,或由1变成0。一般逻辑非运算的运算符记为“ˉ”,设x=x0x1x2…xn,则逻辑非标记为: = n 【例2-23】 设x=10100101,求 。 解:按照逻辑非运算规则,得 = 01011010 2.逻辑与运算 逻辑与(AND)也称为逻辑乘,表示两个操作数相同位按位做“与” 运算,规则是:两个都是1 则结果为1 ,两个中只要有1 个为0 结果就是0,一般逻辑与运算的运算符记为“∧” 或“·”。 【例2-24】 设x=01011101,y=10011000,求x∧y。 解: 0 1 0 1 1 1 0 1 ∧ 1 0 0 1 1 0 0 1 0 0 0 1 1 0 0 1 所以 x∧y=00011001 逻辑与的特点:不管二进制位是1或0,同0做逻辑与则变成0 ,而同1做逻辑与则保持原有不变。利用逻辑与的这一特点可以对数据的某几位清0 ,而其他位保持不变。 【例2-25】需要对x =01011101的最低两位清0,而其他各位保持不变。 解:根据题意,构造出y =11111100,然后计算出x∧y,即可得到想要结果。 0 1 0 1 1 1 0 1 ∧ 1 1 1 1 1 1 0 0 0 1 0 1 1 1 0 0 所以x∧y=01011100 3.逻辑或运算 逻辑或运算(OR)也称为叫逻辑加,表示两个操作数相同位按位做“或” 运算,运算规则是:如果两个都是0 则结果为0 ,如果两个中至少一个为1,则结果就是1。一般逻辑或运算的运算符记为“∨” 或“+”。 【例2-26】 设x=01011101,y=10011001,求x∨y。 解: 0 1 0 1 1 1 0 1 ∨ 1 0 0 1 1 0 0 1 1 1 0 1 1 1 0 1 所以x∨y=11011101 逻辑或的特点:不管二进制数0或1,同1做逻辑或都会变成1 ,同0做逻辑则保持原有数据不变。利用逻辑或这一特点,可对数据的某几位“置1” ,而其他位保持不变。例如 【例2-27】需要对x =01011101的最低两位设置为1,而其他各位保持不变。 解:根据题意构造出y =00000011,然后计算x∨y,即可得到想要结果。 0 1 0 1 1 1 0 1 ∨ 0 0 0 0 0 0 1 1 0 1 0 1 1 1 1 1 所以 x∨y=01011111 4.逻辑异或运算(XOR) 逻辑异或运算(XOR)又称按位加,表示两个操作数相同位按位“模2加”运算,运算规则是:如果两个都相同则结果为0,如果两个不同则结果为1,一般逻辑异或运算的运算符记为“⊕”。 【例2-28】 设x=01011101,y=10011001,求x⊕y。 解: 0 1 0 1 1 1 0 1 ⊕ 1 0 0 1 1 0 0 1 1 1 0 0 0 1 0 0 所以 x⊕y=11000100 逻辑异或有两个重要特点: (1)一个二进制位,同1做异或会变“反”,同0做异或则保持不变。利用这一特点,可对数据的某几位取“反”,而其他位保持不变。 【例2-29】需要对x =01011101的最低两位取反1,而其他各位保持不变。解:根据题意构造出y =00000011,然后计算x⊕y,即可得到想要结果。 0 1 0 1 1 1 0 1 ⊕ 0 0 0 0 0 0 1 1 0 1 0 1 1 1 1 0 所以, x⊕y=01011110 异或运算通常用于判断两位是否相同场合,例如,单符号位溢出判断的逻辑电路,奇偶校验位的逻辑电路。 (2)对数据A施加异或运算B,假设得到结果C,即C =A⊕B,如果对结果C再次施加异或运算B,则可从C中恢复出A,即C⊕B =A,这个特性在数据加密传输中得到广泛应用,其中A称为明文,B称为共享密钥,C称为密文。具体应用方式是:发送者对需要发送的信息A做加密,即用密钥B对其做异或运算,得到密文C =A⊕B,然后将密文C发送给接收者;接收者收到密文C后,首先做解密,即用密钥B对其做异或运算C⊕B =A,从而会恢复出明文A,而由于在传送过程中信息A是以加密形式C传输的,因此具有较强的安全性。 逻辑与、或、异或运算规则,总结如表2-12所示。 表2-12 逻辑运算与、或、异或规则 A B 0 0 0 1 1 0 1 1 与 A∧B 0 0 0 1 或 A∨B 0 1 1 1 异或 A⊕B 0 1 1 0 2.4.4 定点运算器 运算器是计算机五大组成部件之一,是负责数据加工处理的部件。冯诺依曼提出的IAS计算机就是以运算器作为中心的,运算器也是“计算机”名称中计算功能的主要体现者。 运算器的主要功能是执行算术运算和逻辑运算,算术运算负责对数值数据进行加、减、乘、除等运算,逻辑运算则负责对无符号数据进行与、或、非、异或等运算,此外运算器还能执行移位运算。 为了实现这些功能,运算器的基本结构包括算术逻辑单元(Arithmetic Logic Unit,ALU)、寄存器、数据总线及其他逻辑部件。其中ALU是具体执行算术与逻辑运算的单元,是运算器的核心,由加法器及其他逻辑运算单元组成;寄存器用于存放参与运算的操作数,其中的累加器是一个特殊的寄存器,除了可以存放操作数外,还用于存放中间及最后结果;数据总线用于完成运算器内部的数据传送。 运算器的基本结构如图2-9所示,其主要部件及完成的主要功能归结如下。 (1)ALU:运算器核心功能部件,用于实现算术和逻辑运算。 (2)通用寄存器组:存放待加工的信息或加工后的信息。 (3)多路开关或数据锁存器:用于控制ALU的输入端来自哪组寄存器或者哪个总线接收器。 (4)输出移位开关:用于将ALU的运算结果送往发送器然后到达总线,以便进一步送到存储器或输入输出设备,或者送往通用寄存器,作为下一次运算时ALU的输入项。 (5)传输总线、总线接收器和发送器:是ALU与外部部件之间的数据通路,总线接收器和发送器通常由三态门构成。 下面对各个功能部件做详细说明。 图2-9 运算器的基本结构 1.ALU (1)ALU和运算功能 一般地,ALU不仅具有多种算术运算和逻辑运算功能,而且还具有先行进位逻辑,从而能实现高速运算。 从ALU执行的算术运算功能看,基本的ALU都直接支持整数的加法运算,通常采用补码运算,在此基础上,又可以利用加、减法运算功能并通过软件编程支持乘、除法或更复杂的运算。事实上,任何计算机都可以通过编程来执行任何算术运算,如果其ALU不能从硬件上直接支持,则该运算将用软件方式实现,但需要花费较多的时间。 有些ALU除了直接支持基本加、减法运算外,还可以直接支持乘法、除法,甚至三角函数和平方根运算;有些ALU则可以直接使用浮点来表示有限精度的实数。 在图形处理器和具有单指令流多数据流SIMD(Single Instruction Multiple Data)和多指令流多数据流MIMD(Multiple Instruction Multiple Data)特性的计算机中,通常具有可以执行矢量和矩阵运算的ALU。 从计算机具备的ALU数量看,很多计算机内部只有一个ALU,而超标量(Superscalar)计算机包含多个ALU,可以同时处理多条指令。 ALU的逻辑运算功能是分支和循环结构程序设计的基础,利用逻辑与、或、异或、非可以创建复杂的条件语句,处理复杂的布尔逻辑,另外,ALU还具有比较数值的功能,并根据比较结果(例如相等、大于或小于)来返回一个布尔值——真或假。 (2)ALU的基本组成电路 目前ALU电路已经由集成电路实现,电子元器件74181是能够执行4位二进制代码算术运算和逻辑运算的集成电路芯片。图2-10(a)(b)分别为ALU的外部特性图和71181芯片的外部引脚图,表2-13是74181内部功能的真值表。74181有两种工作方式,即正逻辑和负逻辑,下面以正逻辑为例进行介绍。 图2-10 运算器的框图和外部引脚 表2-13 74181的功能表 在图2-10(a)中,ALU有两组输入端Ai和Bi,一组输出端Fi,还有ki个控制端用来实现ALU的不同功能。 在图2-10(b)中,A0~A3和B0~B3是二组输入端,每组输入端为4位二进制数,F0~F3是一组输出端,SO~S3是控制端,用以选择ALU的功能,C-1是最低位的外来进位位,Cn+4是四位运算产生的进位位。P,G是输出端,可供先行进位位使用。 将多片74181进行级联可以实现8位、16位等二进制的运算。 目前有些集成电路将ALU和寄存器功能集成在一个芯片内,如电子元器件29C101,其外部特性引脚如图2-11所示,它支持16位二进制的运算,同样也支持多片的级联从而实现更多位的运算。 图2-11 29C101的框图和外部引脚 2.数据总线 为了实现运算器内部ALU、多个寄存器以及多路开关等部件的通信,需要设计传送线,从连接结构上看,通常将这些传送线设计成为总线结构,称为数据总线,使不同来源的信息在此总线上分时传送,总线方式可以减少传送线数量。 计算机系统中的总线根据其所处的位置,可以分为内部总线和外部总线(第6章),其中内部总线是指CPU内各部件的连线,显然,运算器中的总线属于内部总线。 3.运算器的基本结构形式 运算器的设计主要是围绕ALU及寄存器在数据总线上如何传送操作数和运算结果来进行的,依据数据传送方便性和操作速度,常见有三种总线结构:单总线结构,双总线结构和三总线结构。采用三种结构运算器的原理图如图2-12(a)(b)(c)所示。 图2-12 三种结构运算器的原理 (1)单总线结构的运算器 单总线结构运算器内部只有一组数据总线,所有部件都连接到这组总线上,数据可以在任何两个寄存器之间,或者在任一个寄存器和ALU 之间传送。 单总线结构运算器的工作原理和步骤如下:假设在通用寄存器中有两个操作数x,y,需要在运算器中计算x+y,并将运算结果放回寄存器,该任务需要三次数据传送,花费三个单位时间。 操作数x从寄存器通过总线传送到ALU的A缓冲寄存器; 操作数y从寄存器通过总线传送到ALU的B缓冲寄存器; 在ALU完成加法操作x+y,同时计算结果通过总线送回通用寄存器。 单总线结构运算器优点是总线的控制电路比较简单,有利于提高大规模集成电路的集成度,缺点是是操作速度较慢,执行一个双操作数的运算,一般需要三次数据传送。 (2)双总线结构的运算器 双总线结构运算器的内部有两条数据总线,分别连接到ALU的两个输入端, 特殊寄存器分为两组,分别与两条总线相连。为了防止总线冲突(例如ALU输出结果与两条总线输入操作数都要占用总线),必须在ALU 的输出端设置缓冲寄存器。 仍以上面加法运算为例,双总线结构的工作原理和步骤如下,需要两次数据传送,花费两个单位时间。 操作数x,y从寄存器发出,并分别通过总线1,2传送到ALU的A,B缓冲寄存器,并同时在ALU完成运算,运算结果则送到ALU输出端的缓冲寄存器; 缓冲寄存器中存放的运算结果通过总线1送到通用寄存器。 双总线结构运算器比单总线结构运算器速度快,执行一个双操作数的运算,一般只需要两次数据传送,花费两个单位时间,但是总线控制电路要相对复杂些。 3.三总线结构的运算器 三总线结构的运算器内部有三条总线,为了简化设备,每条数据总线都设计成单向总线,寄存器可以输出数据至总线1和总线2,而总线1和总线2的数据分别送往ALU的两个输入端,与之相反,ALU的输出端只能送往总线3,而寄存器也只能接收来自总线3的数据。另外,由于每条总线都是单向传输数据,为了避免寄存器之间的数据传送路线因经过ALU 而降低速度,在三总线结构运算器中还专门设置了总线旁路器,只要开通总线旁路器,总线2的数据就可以直接送往总线3 而不需要经过ALU,由此大大提高寄存器之间的数据传送速度。 仍以上面加法运算为例,三总线结构的工作原理和步骤如下,仅需要一次数据传送,花费一个单位时间。 操作数x,y从寄存器出发,分别通过数据总线1,2传送到ALU的A,B缓冲寄存器,并同时在ALU完成运算,将运算结果通过总线3发送到通用寄存器。 三总线结构运算器的速度最快,双操作数运算可以一步完成,但总线控制也是最复杂的。 4.寄存器 寄存器一般指的是通用寄存器,多寄存器是现代计算机系统的结构特点之一。多个寄存器组成一组,称为通用寄存器组,例如寄存器组R0~R7,有8个通用寄存器;有的CPU具有多组通用寄存器,例如4组R0~R7,共32个通用寄存器。利用多寄存器可以存放运算过程的中间结果,使存取数据的速度提高,从而缩短指令周期,加快机器运算速度。 通用寄存器除了用于存放操作数和运算结果外,还可以作为变址寄存器存放变址值,作为堆栈指示器存放堆栈指针等,有些可以被程序员直接使用。在C语言中定义循环变量时,可以使用register修饰词,编译系统会根据系统条件来选择寄存器作为循环变量,与内存变量相比具有更快速度。 在通用寄存器中,有一类功能更强的寄存器称为累加器,累加器是运算器中与ALU直接相连、使用频繁的一种寄存器,每次运算的操作数或运算的中间结果大多存放在累加器中。由于累加器与很多指令都相关,在一些CPU设计中,通用寄存器都可以作为累加器使用,为指令的使用带来方便。 与通用寄存器对应,还有一类寄存器称为专用寄存器,专用寄存器是计算机内部使用的寄存器,有多种特殊功能寄存器,例如程序计数器PC用于存放下一条指令的内存地址,指令寄存器IR用于存放当执行的指令,这些寄存器功能将在第5章中介绍。专用寄存器对于程序员而言是透明的,不能由程序员直接使用。 2.5本章小结 计算机是处理信息的机器,在计算机内部使用二进制指令来处理二进制数据,二进制相比十进制具有更多优势。由于二进制数据书写起来比较长,为书面表达方便,常常使用十六进制形式。二进制的基本问题是二进制与其他进制的转换、二进制编码表示问题。其中,将十进制小数转换为二进制小数时,整数部分采用除基取余方法,能得到精确值,小数部分采用乘基取整方法,但一般得不到精确值,需要根据精度要求,应设定停止迭代条件。 数据的各种编码表示实质都是二进制形式的,由于数据类型或应用需求不同而引出各种不同编码。对于有符号整数,需要将数值与符号位统一编码,由此引出原码、反码、补码和移码。对于一般小数,预先规定好小数点位置,或在数据最左端(纯小数)或在数据最右端(纯整数),这就是定点数。定点数表示的数据范围有限,因此借鉴科学计数法形式,引入了浮点数表示方法,其中关于浮点数的重要国际标准是IEEE-754,通常高级编程语言中的float和double数据类型都采用这个标准。 十进制是最常使用进位计数制,在计算机中为十进制数专门规定编码方法,如BCD码,这是一种加权码,且各权取值为“8421”的二进制编码方法。 在非数值型数据中,英文字母、阿拉伯数字以及常用的符号广泛使用ASCII码表示,标准ASCII码使用7位二进制数表示,加上固定设置为0的1个最高位共占用8位,即一个字节。Unicode码是一种全新的编码,其设计目标实现跨语言、跨平台进行文本转换和处理的要求,常用的Unicode码是UCS-2和UCS-4编码。 汉字一般需要采用两个或更多字节进行编码,根据汉字在计算机中不同处理阶段的使用需求,将汉字编码分为了输入码,交换码、机内码和输出码。其中交换码也称为汉字国标码GB2312-80,而机内码是计算机内部处理汉字信息的编码。为了区分ASCII码,机内码由国标码的每个字节各加上80H构成。输出码对应的是字型码,分为点阵字库和矢量字库,点阵字库是有行列像素组成的位图,矢量字库保存的是每一个汉字的描述信息,它的取字形速度快,字体放大后质量不受影响。 不同的数据类型具有不同的宽度,而计算机也有不同的位宽,将一个数据保存到计算机内存时,这个数据的高、低位存放顺序上有两种格式,一个是大端方式,即高位放在低地址空间,低位放在高地址空间,另一种是小端方式,即高位放在高地址空间,低位放在低地址空间,不同体系结构的计算机采用了各自方式。 数据在存取、交换和传输时都可能发生错误,因此在实际应用中采用校验码和纠错码保证数据的可靠性。校验码是在有效数据之后再增加校验数据,两者一并存储或传输,以后再次访问,或者接收方使用时,利用有效数据和校验数据就可以判断有效数据的正确性。奇偶校验是一种常用的校验方式,交叉校验可以检查两位同时出错的情况,或者纠正1位的错误。海明校验本质上是一种多重奇偶校验码,且具有纠错能力。循环冗余校验通过数学运算建立数据和校验位之间的约定关系,是校验和纠错能力更强的校验码。 定点运算是CPU的基本功能,定点加、减运算使用补码运算最为便捷,定点乘、除法运算可以采用原码也可采用补码运算。除了四种运算外,CPU还具有与、或、非、异或等逻辑运算功能,以及移位运算功能。运算器是计算机五大部件之一,从组成结构上看,运算器通常包括算术逻辑单元、寄存器、数据总线及其他逻辑部件,运算器内部的ALU,寄存器以及多路开关等部件采用总线结构连接并进行通信,这种总线结构有单总线结构,双总线结构和三总线结构,对指定的操作,单总线结构需要步骤多,但结构简单,而三总线结构需要步骤少,但结构复杂。 在计算机数值计算中广泛使用浮点运算,浮点运算的加、减法和乘、法运算相对定点数,需要更多的步骤,计算也较为繁琐,现代的计算机大都提供了专门的浮点运算器,并且都集成在CPU芯片内部。流水线是一种多条指令重叠执行的处理机实现技术,能够实现时间并行性。把输入的任务分割为一系列子任务,各子任务能在流水线各个阶段并发执行,将任务连续不断地输入流水线,实现子任务级的并行。 计算机发展历程中,其结构从以运算器为中心,过渡到以存储器为中心,本章介绍了CPU的重要部件运算器,接下来将介绍CPU中另一个重要部件——存储器。 习 题 1.计算机中将数据分成数值型数据和非数值型数据两类,下面属于非数值数据类型的是: A.3.14 B.字母 C.算术符号 D.MP3歌曲 (B,C,D) 2.数值型数据和非数值型数据,在计算机内部都要被转换为 进制的数码进行存储、传送和加工处理。 (二) 3.数值数据可以采用多种进制表示,当对同一个数值数据采用不同进制表示时,基数越大,表示这个数所用位数就越 。 (小或少) 4.计算机中常用的数据表示格式,根据小数点位置是否固定,有两种: 数和 数。 (定点,浮点) 5.1985年,IEEE(Institute of Electrical and Electronics Engineers,美国电气和电子工程师协会)提出了IEEE-754标准,并以此作为 数据类型 的统一标准。 (浮点) 6.在IEEE-754标准浮点格式中,单精度格式采用 位二进制数表示,双精度格式采用 二进制数表示。 (32, 64) 7.一个浮点数有多种表示形式,为了提高浮点数的表示精度,当尾数不为 时,通过修改阶码并移动小数点,使尾数域的最高有效位为 ,称为浮点数的规格化表示。 A.0,0 B.0,1 C,1,0 D.1,1 (B) 8.标准ASCII码采用 位二进制数表示1个字符,在计算机中用一个字节来存放一个ASCII码,其特点是字节的 位固定为0,并常常用于区别西文字符和汉字字符。 (7,最高) 9.汉字的编码方法中,当汉字用一个由m×n个像素组成的位图表示时,称为字模,我们将其称为 字库,当汉字用汉字描述信息(如一个笔画的起始坐标、终止坐标、半径、弧度等等),改变文字的字号只需要改变缩放系数,我们将其称为 字库 (点阵,矢量) 10.对于下面三种非数值编码方法,在表示一个字符时采用的二进制位数不同,其中扩展ASCII码用 位表示,Unicode UCS-2用 位表示,Unicode UCS-4用 位表示。 A.4,8,16 B.7,14,28 C.8,16,32 D,16,32,64 (C) 11.在我国使用的计算机汉字操作系统平台中,下面哪个字符集是简体字符集 。 A.GB2312 B.BIG5 C.GBK D.GB18030 (A) 12.在计算机数据处理中,当采用奇校验的方式时,如果有效信息位中“1”个数为奇数,则奇校验位为 。 (0) 13.在计算机数据处理中,当采用偶校验的方式时,如果有效信息位中“1”个数为偶数,则偶校验位为 。 (0) 14.根据奇偶校验的特点,当一个数据采用奇偶校验时,可以检查出的错误包括 A.一位错误 B. 两位错误 C.奇数位错误 D.出错位置 (A.C) 15.交叉奇偶校验,采用纵向、横向同时校验的方法,可发现 位(多少位)同时错。 (2) 16.在定点 运算中,为了判断溢出是否发生,可采用双符号位检测法。不论溢出与否,其 符号位始终指示正确的符号。 A.小数,最高 B.小数,最低 C.整数,最高 D.整数,最低 (A,C) 17.定点加、减法运算属于算术运算,要考虑参加运算数据的符号和编码格式,现代计算机的运算器一般都采用 码形式加减法。 (补) 18.在定点二进制运算器中,减法运算一般通过 来实现。 A.原码运算的二进制减法器 B.补码运算的二进制减法器 C.补码运算的十进制加法器 D.补码运算的二进制加法器 (D) 19.在计算机的逻辑运算中,对任何一个二进制数A,与另一个二进制数B进行某种逻辑运算后,再对结果与B进行同样一次该逻辑运算,则运算结果又变成了A,则这种逻辑运算是 运算。 (异或) 20.运算器由ALU、 、数据总线和其他逻辑部件组成。 (寄存器) 21.寄存器用于存放参与运算的操作数,其中的 是一个特殊的寄存器,除了可以存放操作数外,还用于存放中间结果和最后结果。 (累加器) 22.一般地,根据总线的多少,运算器的基本结构形式可以分为 结构的运算器、 结构的运算器和 结构的运算器。 (单总线, 双总线, 三总线) 23.在定点运算器的结构中,对于一个双操作数的运算,一般单总线结构的运算器需要 次数据传送,双总线结构的运算器需要 次数据传送,三总线结构的运算器 步完成。 (3,2,1) 24.根据流水线的原理,为了实现流水,把输入的任务分割为一系列子任务,各子任务能在流水线各个阶段并发执行,为了避免某一阶段处理时间较长造成其他阶段空转等待,原则上要求各个阶段的处理时间长度 。 (相等) 25.从理论上讲,一个具有k 级过程段的流水线处理 n 个任务需要的时钟周期数为:k个周期后,流水线被装满,剩余的n-1个任务只需 个周期就完成。 n-1 26.请简述运算器的单总线、双总线和三总线形式彼此之间有什么不同? 答: 1)单总线结构的运算器: 所有部件连接到同一条总线上,运算器内部只有一组数据总线,数据可以在任何两个寄存器之间,或者在任一个寄存器和ALU之间传送。 执行一个双操作数的运算, 一般需要三次数据传送,花费三个单元时间。 2)双总线结构的运算器: 有两条总线同时连接ALU的两个输入端,可以与通用寄存器双向传送数据 一个双操作数运算,需要两次数据传送(2个单元时间) 3)双总线结构的运算器:共有三条总线。ALU两个输入端由两条总线供给,输出与第三条总线相连。 在三种总线中,速度最快,双操作数运算可以一步完成。 27.将下列数转化为其它进制表示(十进制,二进制和十六进制)。 (1)24.8125 (2)101101.011B (3) 31AB.CH 解: (1)十进制 24.8125D 二进制 11000.1101B 十六进制18.DH (2)十进制 45.375D 二进制 101101.0111011B 十六进制2D.6H (3)十进制 12715.75D 二进制 11 0001 1010 1011.11B 十六进制31AB.CH 28.对于8位计算机,求出下面个数的原码、反码和补码表示。 (1)0.546875 (2)-0.1796875 (3)-127 (4)-1 (5)100 (6)127 解: (1)0.546875转换为二进制数 0.100011B [0.546875]原= 0.100011B [0.546875]反= 0.100011B [0.546875]补 =0.100011B (2)-0.1786875转换为二进制数 -0.0010111B [-0.1786875]原= 1.0010111B [-0.1786875]反=1.1101000B [-0.1786875]补 =1.1101001B (3)-127转换为二进制数 -1111111B [-1111111]原= 11111111B [-1111111]反=10000000B [-1111111]补 =10000001B (4)-1转换为二进制数 -1B [-1]原= 10000001B [-1]反=11111110B [-1]补 =11111111B (5)100转换为二进制数 1100100B [1100100]原= 01100100B [1100100]反= 01100100B [1100100]补 =01100100B (6)127转换为二进制数 1111111B [111111]原= 0111111 [111111]反=0111111 [111111]补 =0111111 29.已知[x]补如下,求原码和真值 (1)11100101 (2)10000000 (3)01010011 (4)00110101 解: (1)因为 [x]补=11100101,为负数,所以原码是符号位不变,数值位取反+1,所以[x]原=10011011 真值为-27 (2)因为 [x]补=10000000,为负数,所以原码是符号位不变,数值位取反+1,所以[x]原=10000000,原码对应真值为-0,[x]补=10000000真值定义为-128。 (3)因为 [x]补=01010011,为正数,所以原码与补码相同,所以[x]原=01010011 真值为+83 (4)因为 [x]补=00110101,为正数,所以原码与补码相同,所以[x]原=00110101 真值为+53 30.运算题:已知x和y,用双符号位补码计算x+y,同时指出运算结果是否溢出。 (1) x=0.11011 y=0.00011 (2) x=0.11011 y=-0.1011 解: (1)x=0.11011 y=0.00011 [x]补=00.11011, [y]补= 00.00011 [x]补 00.11011 + [y]补 00.00011 [x+y]补 00.11110 (mod 4) 因为[x+y]补 =00.11110,结果中双符号为00,同号,未发生溢出,接着需要将结果转化为真值,结果补码是[x+y]补 =00.11110,真值为+0.11110。 (2)x=0.11011 y=-0.1011 [x]补= 00.11011, [y]补= 11.01010 [x]补 00.11011 + [y]补 11.01010 [x+y]补 100.00101 (mod 2) 因为[x+y]补 =100.00101,最前的1舍去,结果为00.00101,同号,表示没有发生溢出,接着需要将结果转化为真值,结果补码是[x+y]补 =00.00101,真值是x+y= +0.00101。 31.计算题:已知x和y,用双符号位补码计算x-y,同时指出运算结果是否溢出。 (1) x=0.10111 y=-0.11111 (2) x=0.10111 y=-0.11011 (3)x=0.10111 y= 0.11011(注意:3为补充题,书上没有) 解: (1)x=0.10111 y=-0.11111 [x]补=00.10111, [y]补= 11.00001,[-y]补= 00.11111 [x]补 00.10111 + [-y]补 00.11111 [x+y]补 01.10110 (mod 4) 因为[x+y]补 =01.10110,结果中双符号为01,不同号,表示发生了溢出,并且为正溢出,计算结束。 (2)x=0.10111 y=-0.11011 [x]补=00.10111, [y]补= 11.00101,[-y]补= 00.11011 [x]补 00.10111 + [-y]补 00.11011 [x+y]补 01.100010 (mod 4) 因为[x+y]补 =01.10010,结果中双符号为01,不同号,表示发生了溢出,并且为正溢出,计算结束。 (3)x=0.10111 y= 0.11011 [x]补=00.10111, [y]补= 00.11011, [-y]补= 11.00101 [x]补 00.10111 + [-y]补 11.00101 [x+y]补 11.11100 (mod 4) 因为[x+y]补 =11.11100,结果中双符号为11,同号,表示没有发生溢出,接着需要将结果转化为真值,结果补码是[x+y]补 =11.11100,真值是x+y= -0.00100。