《计算机组成与体系结构(原书第4版)》 —2.4 有符号整数表示
2.4 有符号整数表示
我们已经讲述了如何将无符号整数从一个基转换为另一个基。对于有符号数的转换,则还需要解决一些其他问题。当在一个程序中声明一个整型变量时,许多编程语言会自动为其分配存储区,该存储区中的第一位作为符号。按照约定,最高位为“1”时表示负数。该存储区域可以小到一个8位的字节或大到几个字,这取决于编程语言和计算机系统。剩余位(符号位之后)用于表示数字本身。
有符号数的表示方式取决于所使用的方法。有3种常用的方法。最直观的方法是有符号量值,也称为原码,它使用除符号位之外的剩余位来表示数的量值。这种方法和其他两种使用补码概念的方法将在后面介绍。
2.4.1 原码
到目前为止,我们可能忽略了负数的二进制表示。正整数和负整数的集合称为有符号整数的集合。将有符号整数表示为二进制的问题是符号——我们应该如何对这个数字的实际符号进行编码呢?原码表示是解决这个问题的一种方法。顾名思义,对于一个原码来说,最左边的位(也称为高阶位或最高有效位)是符号位,而其余位表示数的量值(或绝对值)。例如,在8位字中,-1表示为100000012,+1表示为000000012。在使用原码表示的计算机系统中,用8位存储整数,7位用于表示数的量值。这意味着8位字可以表示的最大整数是27-1或127(最高位是一个0,后跟7个1)。最小整数是111111112或-127。因此,N位可以表示的范围是从-(2(N-1)-1)~2(N-1)-1。
计算机必须能够对用该方法表示的整数执行算术运算。原码运算基本上与人用铅笔和纸张使用的方法相同,但这种方法可能很快会让人感到有些混乱。作为示例,考虑加法规则:(1)如果符号相同,则数值相加并使用相同的符号作为结果;(2)如果符号不同,则必须确定哪个操作数具有较大值。结果的符号与操作数中较大数值的符号相同,并且数值必须从较大操作数减去(不加)较小操作数来获得。如果你仔细考虑这些规则,就会知道这是你手算有符号数时的方法。
我们根据它们的符号以一定的方式排列操作数,在不考虑符号的情况下进行运算,然后在计算完成后根据情况补上符号。当在一个8位字中按这个想法建模时,我们必须小心因为结果中只包括7位,丢弃高阶位上发生的任何进位。
例2.10使用原码运算,计算010011112加001000112的结果。
这个算术运算的过程与十进制加法一样,包括进位,直到得到从右边数七位的结果为止。如果在这里有一个进位,则我们说有溢出情况并且丢弃进位,导致不正确的和。在此示例中没有溢出。
我们发现在使用原码表示时,010011112+001000112=011100102。
符号位应分开考虑,因为它们仅需在加法完成后才去处理。在这种情况下,我们得到的是两个正数的和,这个和是正数。当结果符号不正确时,在有符号数中会发生溢出(因此产生错误的结果)。
在原码表示中,符号位仅用于表示符号,因此不能进位至此位。如果第七位发生进位,结果将被截断当成第七位溢出,并产生一个不正确的和。(例2.11说明了这种溢出情况。)只要有最微小的可能性发生,谨慎的程序员都要通过检查溢出条件避免“百万美元”的错误。如果没有丢弃溢出位,它将进入符号位,导致更无法容忍的两个正数之和变为负数的结果。(想象在程序的下一步中会发生什么,取平方根或读日志的结果!)
例2.11使用原码运算,计算010011112加011000112的结果。
得到了错误的结果是79+99=50。尝试快速方法将一个二进制数转换为十进制数的最快方法是称为倍和法(double-dabble或double-dibble)。这种方法建立的基础是,在二进制数中,2的下一个幂次是前一个幂次的两倍。计算从最左边的位开始,并移向最右边的位。第一位被加倍并加到下一位。然后将该和加倍并加到下一位。对每一位重复该过程,直到最右边的位。
例1
例2
和加法一样,原码减法与用笔和纸进行的十进制算术运算很类似,它有时需要从被减数上借数。
例2.12使用原码运算,计算011000112减去010011112。
我们发现采用原码表示时,011000112-010011112=000101002。
例2.13使用原码算法计算010011112(79)减去011000112(99)。
通过检查,我们看到,减数011000112比被减数010011112大,根据例2.12得到的结果我们知道,这两个数字的差是00101002。由于减数比被减数大,所以我们需要做的是改变差的符号。因此我们发现用原码表示的结果是010011112-011000112=100101002。
我们知道,减法与“加上相反数”是一样的,这相当于对减数取反然后用加法代替减法(这样做常常比执行减法需要借位更简单,特别是在处理二进制数时)。因此,我们需要看一些同时涉及正数和负数的例子。回想加法规则:(1)如果符号是相同的,两个数直接相加,结果符号是相同的;(2)如果符号不同,必须确定哪个数较大,结果的符号是大数的符号,并且结果应该是大数减去小数(不是相加)。
例2.14使用原码算法计算100100112(-19)加000011012(+13)
第一个数是负数,因为它的符号位是1,第二个数(加数)是正数,我们实际需要做的是减法。首先,我们确定这两个数哪个较大,并使用较大的数作为被加数。它的符号将来就是结果的符号。
由于包含符号位,所以我们看到使用原码表示时的结果是100100112-000011012=100001102。
例2.15使用原码算法计算101010112(-43)减去100110002(-24)。
我们可以用-(-24)(即24),将减法转换为加法,然后就可以将24加到-43上了。这样就给了我们一个-43+24的新问题。然而,我们从上面说的加法规则中知道,因为符号不同,所以我们实际必须用较大值减去较小值(或43减去24),使结果为负(因为43比24大)。
请注意,在我们执行完减法之前,不用关心符号问题。我们知道答案一定是负数。所以,我们最终使用原码表示为101010112-100110002=100100112。
阅读了前面的例子后,你可能已经注意到我们不得不问自己的问题是哪个数更大?我是否减去了负数?我从被减数中借数多少次?以这种方式执行算术运算的计算机必须做出同样多的决策(尽管速度更快)。由于这个原码0有两种表示方式10000000和00000000(从数学上讲,这根本不应该发生),因此逻辑(和电路)更为复杂。用更简单的方法表示有符号数会使电路更简单而且更便宜。这些更简单的方法是以基数补码系统为依据的。
- 点赞
- 收藏
- 关注作者
评论(0)