*1.6 整数的存储
数学家们长久以来就对数字记数系统很感兴趣,而且他们的许多想法已经被证明与数字电路的设计是相符的。本节,我们将研究其中两种记数系统:二进制补码记数法和余码记数法。它们都是计算设备用于表示整数的方法。虽然这些系统都是基于二进制系统的,但是它们增加了一些其他的特性,因而与计算机设计更加兼容。尽管它们有这么多的优点,但是它们也有缺点。我们的目标是了解这些特性以及它们是如何影响计算机用法的。
模拟与数字
在21世纪之前,许多研究人员都在讨论数字技术和模拟技术的优缺点。在数字系统里,一个数值会被编码成一系列数字,存储在若干设备中,每个设备表示一个数字。在模拟系统里,每个数值都存储在一个单独的设备里,这个设备可以表示一个连续范围内的任何数值。
让我们用水桶当存储设备来比较这两种方法。为了模拟数字系统,我们让一个空桶表示数字0,一个满桶表示数字1,然后我们利用浮点记数法(见1.7节)将一个数字值存储在一排水桶中。相反,为了模拟模拟系统,我们用水桶水位表示数字值。乍一看,模拟系统看起来更精确,因为它不会有数字系统中的截断误差(见1.7节)。不过,在模拟系统中,水桶的任何移动都会使水位检测出错,而在数字系统中,则必须有剧烈的晃动才能区分出水桶是满的还是空的。因此,数字系统不像模拟系统对错误那样敏感。由于数字系统的这种健壮性,许多原来基于模拟技术的应用(如电话通信、音频录制和电视)都转而使用数字技术。
1.6.1 二进制补码记数法
现今计算机中最流行的整数表示系统是二进制补码(two’s complement)记数法。这个系统采用固定数目的二进制位来表示系统中的每一个数值。现今设备中普遍采用二进制补码系统,其中每个数值用一个32位的模式表示。这种大系统能表示很大范围的数字,但不方便演示。因此,在学习二进制补码系统的特性时,我们将着重介绍较小的系统。
图1-19列出了两种完整的二进制补码系统,一种基于长度为3的位模式,另一种基于长度为4的位模式。要构造这种系统,首先要规定一组适当长度的二进制0,接着用二进制计数,直到只有一个0、其他都是1的模式形成。这些模式表示数值0, 1, 2, 3, …。要想获得表示负值的模式,首先要规定一组适当长度的二进制1,接着按照二进制反向计数,直到只有一个1、其他都是0的模式形成。这些模式表示数值-1, -2, -3, …。(如果你认为利用二进制反向计数有困难,那么可以从表格底部只有一个1、其他都为0的模式开始,向上计数到全是1的模式。)
注意,在二进制补码系统中,位模式最左边的二进制位指明了所表示的数值的符号。因此,最左边的位常称为符号位(sign bit)。在二进制补码系统中,符号位为1的模式表示负值,符号位为0的模式表示非负值。
在二进制补码系统中,绝对值相同的正负数值的表示模式之间有一种对应关系,从右向左读时,直到第一个二进制1(包括),它们都是相同的。然后,以这个1为分界线,左面的位模式互为补码。要得到一个模式的补码(complement),需要将所有的二进制0转换为1,并将所有的二进制1转换为0。例如,图1-19中的4位系统,表示2和-2的模式都是以10结束,但是表示2的模式开始为00,而表示-2的模式开始为11。观察到这一点,我们就可以得出在绝对值相同的、表示正负值的位模式之间进行转换的算法。我们只需要从右到左复制原始的模式直到第一个1,接着在将剩余位转换为最终位模式时,对这些剩余位取反(图1-20)。
理解了二进制补码系统的这些基本特性,还可以得出二进制补码表示法的一个解码算法。如果要解码的模式有一个符号位0,我们仅仅需要读出这个数值,就好像这个模式是一个二进制表示。例如,0110表示十进制数值6,因为110是6的二进制表示。如果要解码的模式有一个符号位1,我们就知道表示的数值是负的,而我们所要做的就是找到其绝对值。为了实现这个目的,我们首先要利用图1-20中“复制和取反”的步骤,然后对获得的模式进行解码,就仿佛它只是一个简单的二进制表示。例如,为了对模式1010解码,我们首先要意识到,因为这个符号位是1,表示的数值就是负的。因此,我们利用“复制和取反”步骤获得模式0110,认识到这是6的二进制表示,然后得出结论:原始的模式表示-6。
1.二进制补码记数法中的加法
为了计算二进制补码记数法中的数值相加,我们采用了二进制加法中使用的算法,只是包括答案在内的所有位模式长度都相同。这就意味着,在做二进制补码系统的加法时,如果最后一个进位导致答案左边产生了附加位,那么这个附加位一定会被截断。因此,“加法运算”0101和0010得出0111,0111和1011得出0010(0111+1011=10010,被截断为0010)。
根据这个理解,我们来分析一下图1-21中的3个加法问题。每一个情况,我们都把问题转化为二进制补码记数法(采用长度为4的位模式),演示先前描述过的加法过程,然后对结果进行解码,回到一般的十进制记数法。
注意,图1-21中的第3个问题涉及正数和负数的加法,它展示了二进制补码记数法的一个主要优点:有符号数的任何组合加法,都可以使用相同的算法从而使用相同的电路来实现。这与人们传统的算术运算截然不同。尽管小学生是先学加法,后学减法,但是应用二进制补码记数法的机器只需要知道如何相加就可以了。
例如,减法问题7-5与加法问题7+(-5)是一样的。因此,如果人们命令计算机执行7(存储为0111)减5(存储为0101),那么它首先要将5转换为-5(表示为1011),然后执行0111+1011的加法过程,得到代表数值2的0010,如下所示:
由此我们可以看到,当用二进制补码记数法表示数字值时,只需要将一个加法电路与一个取负电路组合在一起,就足以同时解决加法和减法这两个问题了。(这些电路的图示及解释详见附录B。)
2.溢出问题
我们在前面的例子中避开了这样一个问题:任意一个二进制补码系统对所能表示的数值大小都有限制。当使用4位模式二进制补码时,可以表示的最大正整数是7,最小负整数是-8。具体来说,就是无法表示数值9,这就意味着我们不能指望得出5+4的正确答案。事实上,它的结果会为-7。这种现象称为溢出(overflow)。也就是说,溢出指的是这样一个问题,即计算得出的数值超出了可以表示的数值范围。使用二进制补码记数法时,两个正值相加或两个负值相加都可能会出现这种情况。无论哪种情况,检查答案的符号位就可以发现溢出的条件。如果两个正值相加的结果是负值的模式,或者两个负值相加的结果为正,那么就发生了溢出问题。
当然,使用二进制补码系统的大多数计算机的位模式,都比我们上面例子中给出的长,因而在进行较大数值操作时不会产生溢出。现在,人们普遍使用二进制补码记数法的32位模式来存储数值,可以得到的最大正值是2 147 483 647。如果需要更大的数值,我们可以使用更长的位模式,或者改变度量单位。例如,在解答一个问题时用英尺代替英寸,所得的数值就会变小,而且也可以达到所要求的精确度。
关键问题是计算机会制造错误。因此,使用机器的人一定要意识到可能涉及的危险。其中一个问题就是,计算机程序员和使用者会自满而导致忽视一个事实——小数值可以累加成大数值。例如,人们过去普遍使用二进制补码记数法的16位模式表示数值,这就意味着出现大于或等于215 =32 768的数值时就会产生溢出。1989年9月19日,一家医院多年来运行良好的计算机出现了故障。仔细检查后发现,那天距1900年1月1日共32 768天,而计算机的程序正是基于那个起始日期开始计算日期的。因此,由于溢出原因,1989年9月19日的日期产生了负值——设计计算机程序时没有考虑到这种现象。
1.6.2 余码记数法
表示整数值的另外一种方法是余码记数法(excess notation)。与二进制补码记数法相同,余码记数法中的每一个数值也都是用相同长度的位模式表示的。为了建立余码系统,我们首先要选择所使用的模式长度,然后根据二进制记数呈现的顺序写下那个长度的所有位模式。接着我们发现,二进制1作为其最高位的第一个模式大约就在数列的中间。我们用这个模式表示0,其前的模式就分别用于表示-1, -2, -3, …,其后的模式分别用于表示1, 2, 3, …。使用长度为4的模式产生的编码如图1-22所示。我们可以看到,模式1101表示数值5,0011表示数值-5。(注意,余码系统和二进制补码系统的区别就是符号位相反。)
图1-22表示的系统称为余8记数法。为了了解其由来,我们先用传统二进制系统的编码解释每一个模式,然后将其与余码记数法表示的数值进行比较。你会发现,每一个模式的二进制解释值都要比余码记数法解释值大8。例如,模式1100在二进制记数法中表示数值12,在余码系统中表示4;0000在二进制记数法中表示数值0,但是在余码系统中表示-8。与此类似,在基于长度为5的位模式的余码系统中,模式10000表示的是0,而不是通常的数值16,该记数法称为余16记数法。同样,你可以证明3位余码系统应该称为余4记数法(见图1-23)。
问题与练习
1.将下面每一个二进制补码表示转换为相应的十进制形式。
a. 00011 b. 01111 c. 11100
d. 11010 e. 00000 f. 10000
2.用8位位模式将下列每一个十进制表示转换为相应的二进制补码形式。
a. 6 b. -6 c. -17
d. 13 e. -1 f. 0
3.假定下列位模式表示的是用二进制补码记数法存储的数值,求出每一个值的负值的二进制补码表示。
a. 00000001 b. 01010101 c. 11111100
d. 11111110 e. 00000000 f. 01111111
4.假定一台机器用二进制补码记数法存储数值,如果机器分别采用下列长度的位模式,那么可以存储的最大数和最小数分别是什么?
a. 4 b. 6 c. 8
5.在下列问题中,每个位模式表示一个用二进制补码存储的数值。请执行文中所述的加法过程,按照二进制补码记数法求出它们的答案。并将问题及答案转换为十进制记数法进行验证。
a. 0101+0010 b. 0011+0001 c. 0101+1010
d. 1110+0011 e. 1010+1110
6.计算下列由二进制补码记数法表示的问题,但这次要观察溢出问题,并指出哪个答案因产生溢出而不正确。
a. 0100+0011 b. 0101+0110 c. 1010+1010
d. 1010+0111 e. 0111+0001
7.将下列问题从十进制记数法转换为长度为4的位模式的二进制补码记数法,然后将每一个问题转换成一个相应的加法问题(如机器的做法),然后执行加法。将求得的答案转换为十进制记数法进行验证。
a. 6-(-1) b. 3-(-2) c. 4- 6
d. 2-(-4) e. 1- 5
8.在二进制补码记数法里,一个正数和一个负数相加时会产生溢出吗?请说明理由。
9.将下面每一个余8码表示转换为相应的十进制形式(解题时不要看文中的表格)。
a. 1110 b. 0111 c. 1000
d. 0010 e. 0000 f. 1001
10.将下列的每一个十进制表示转换为相应的余8码形式(解题时不要看文中的表格)。
a. 5 b. -5 c. 3
d. 0 e. 7 f. -8
11.数值9可以用余8记数法表示吗?用余4记数法表示6呢?请说明理由。