2.2 带符号二进制数的表示与运算
数分为带符号数和无符号数两种类型。无符号数不分正负,表示无符号数的各二进制数位都是数值位;带符号数有正数和负数之分。在计算机中,用0和1来表示数的正、负。
在计算机中,一个数连同其符号在内的数值化的表示形式称为机器数。一般用最高位表示数的符号。而这个数本身的值称为真值。机器数可以用不同编码方法表示。常用的编码方式有:原码、反码和补码。
2.2.1 带符号二进制数的表示
1.原码
原码表示法规定:最高位是符号位,用0表示正数,用1表示负数。数值部分用该数的二进制绝对值表示。
数x的原码记作[x]原,如机器字长为n,则整数原码的定义如下:
当机器字长n=8时,有
[+0D]原=00000000,[-0D]原=10000000
[+1D]原=00000001,[-1D]原=10000001
[+45D]原=00101101,[-45D]原=10101101
[+127D]原=01111111,[-127D]原=11111111
当机器字长n=16时,有
[+0D]原=0000000000000000,[-0D]原=1000000000000000
[+1D]原=0000000000000001,[-1D]原=1000000000000001
[+45D]原=0000000000101101,[-45D]原=1000000000101101
[+32767D]原=0111111111111111,[-32767D]原=1111111111111111
按照定义,设n为字长,则原码能表示的整数范围是:-(2n-1-1)~+(2n-1-1)。
例如,8位二进制原码表示的整数范围是:-127D~+127D,16位二进制原码表示的整数范围是:-32767D~+32767D。
原码表示法简单直观,与真值之间的转换方便,但由于符号位不能参与运算,而且对于数0有+0和-0两种表示形式,所以用它进行运算不方便。
2.反码
反码表示法规定:一个正数的反码和原码相同;一个负数的反码的符号位与其原码的符号位相同,其余位通过将其原码的数值部分按位求反得到。
数x的反码记作[x]反,如机器字长为n,则整数反码的定义如下:
当机器字长n=8时,有
[+0D]反=00000000,[-0D]反=11111111
[+1D]反=00000001,[-1D]反=11111110
[+45D]反=00101101,[-45D]反=11010010
[+127D]反=01111111,[-127D]反=10000000
当机器字长n=16时,有
[+0D]反=0000000000000000,[-0D]反=1111111111111111
[+1D]反=0000000000000001,[-1D]反=1111111111111110
[+45D]反=0000000000101101,[-45D]反=1111111111010010
[+32767D]反=0111111111111111,[-32767D]反=1000000000000000
按照定义,设n为字长,则反码能表示的整数范围是:-(2n-1-1)~+(2n-1-1)。
例如,8位二进制反码表示整数的范围是-127D~+127D,16位二进制反码表示的整数范围是-32767D~+32767D。
反码与原码所能表示的数的范围相同,而且,数0有+0和-0两种表示形式。所以,用反码进行运算也不方便。
将反码还原为真值的方法是:若反码的最高位为0,则该数是正数,其后的数值部分就是其真值;若反码的最高位为1,则该数是负数,将其后的数值部分按位取反后,即可得到真值。
3.补码
补码表示法规定:一个正数的补码和反码、原码相同;一个负数的补码的符号位与其原码的符号位相同,其余位可通过将其反码数值部分加1得到(但有一个负数例外,详见下面的说明)。
数x的补码记作[x]补,如机器字长为n,则整数补码的定义如下:
当机器字长n=8时,有
[+0D]补=00000000,[-0D]补=00000000
[+1D]补=00000001,[-1D]补=11111111
[+45D]补=00101101,[-45D]补=11010011
[+127D]补=01111111,[-127D]补=10000001
按照定义,设n为字长,则补码能表示的整数范围是:-2n-1~+(2n-1-1)。
例如,8位二进制补码表示的整数范围是-128D~+127D,16位二进制补码表示的整数范围是-32768D~+32767D。
补码比原码、反码所能表示的数的范围大,数0的补码只有一种表示形式,是计算机中采用的带符号数的编码方式。
将补码还原为真值的方法是:若补码的最高位为0,则该数是正数,其后的数值部分就是其真值;若反码的最高位为1,则该数是负数,将其后的数值部分按位取反加1后,即可得到真值。
8位二进制数的部分数的原码、反码、补码表见表2-4。
表2-4 原码、反码、补码表
特别注意:-128D没有原码和反码,其补码通过定义式求得。
2.2.2 带符号二进制数的运算
1.补码运算规则
采用补码表示的带符号数,其符号位和数值位同时参与运算,运算结果仍然是补码。任何两数相加,无论正负,只要把它们的补码相加即可。加法运算得到的结果是两数和的补码。任何两数相减,无论正负,只要把减数相反数的补码与被减数的补码相加即可。减法运算结果是两数差的补码。运算公式如下:
[x+y]补=[x]补+[y]补
[x-y]补=[x]补+[-y]补
从上面的公式可以看出,补码的减法运算可以转换成加法来完成的,因此,在计算机中利用加法器就可以实现补码的加法和减法运算。
2.补码运算的溢出问题
由于计算机的字长有限,因此,所能表示的数是有范围的。当运算结果超过这个范围时,运算结果将出错,这种情况称为溢出。产生溢出的原因是:数值的有效位占据了符号位。补码运算溢出的判定有以下两种。
(1)利用符号位判别运算结果是否溢出
- 若两个同号数相加,结果的符号位与之相反,则溢出;
- 若两个异号数相减,结果的符号位与减数相同,则溢出;
- 若两个异号数相加或两个同号数相减,则不溢出。
(2)利用运算过程中的进位产生情况判别运算结果是否溢出
- 若次高位(最高数值位)和最高位(符号位)不同时产生进位或借位,则溢出;
- 若次高位(最高数值位)和最高位(符号位)都产生进位或借位,则不溢出。
【例2-10】 当字长为8位时,计算-64D+64D。
解
本例中,-64D+64D=0,运算结果在8位补码的表示范围:-128D~+127D之内,不会溢出。通过分析运算过程可知,次高位(最高数值位)和最高位(符号位)都产生了进位。这种情况下,运算过程中产生的进位,自然丢失。根据前述的溢出判别规则,可知运算结果不溢出。
【例2-11】 当字长为8位时,计算127D+1D。
解
本例中,127D+1D=128D,运算结果超出8位补码的表示范围:-128D~+127D,所以溢出。通过分析运算过程可知,次高位(最高数值位)产生了进位,而最高位(符号位)没有产生进位。这就使得和的数值部分占用了符号位,运算结果的符号与两个加数的符号相异,即两正数相加得到了一个负数和。根据前述的溢出判定方法,可知运算结果溢出。