二进制数字0…00000 代表0;0…00001代表1;0…00010代表2;依此类推。但负数又该怎么表示呢?为了表示有符号的数值,大多数计算机系统使用二进制补码系统。有符号数的表示形式有一些基本限制,因此,重要的是要了解如何在计算机系统中以不同的方式表示有符号数和无符号数,以便有效地使用它们。
n 位只能表示2 n 个不同的对象。负数本身是对象,所以必须把2 n 个组合分配给负数和非负数。例如,一个字节可以表示-128~-1的负数及0~127的非负数。16位的字可以表示-32,768~+32,767之间的有符号数。32位的双字可以表示-2,147,483,648~+2,147,483,647之间的数。通常 n 位可以表示 - 2 n-1 ~+2 n-1 - 1之间的有符号数。
二进制补码系统使用高位作为符号位(Sign Bit)。如果高位为0,则该数字为非负数,使用正常的二进制编码;如果高位为1,则该数字为负数,使用二进制补码。下面是一些16位数字的示例:
●$8000(%1000_0000_0000_0000)为负数,因为高位为1。
●$100(%0000_0001_0000_0000)为非负数,因为高位为0。
●$7FFF(%0111_1111_1111_1111)为非负数。
●$FFFF(%1111_1111_1111_1111)为负数。
●$FFF(%0000_1111_1111_1111)为非负数
可以按照如下二进制补码运算来求负:
1.将非负数按位取反;把0全部变成1,把1全部变成0。
2.将取反的结果加1(忽略溢出)。
如果结果为负数(高位为1),就得到了非负数的二进制补码形式。
例如,与十进制数值-5等价的8位表示形式可以这样计算:
1.%0000_01015(二进制)。
2.%1111_1010 所有位取反。
3.%1111_1011 加1得到-5(二进制补码形式)。
不出所料,对-5 求负的结果是5(%0000_0101):
1.%1111_1011-5的二进制补码。
2.%0000_0100所有位取反。
3.%0000_0101 加1得到5(二进制)。
下面我们来看一些对16位数求负的例子。
首先是对32,767($7FFF)求负:
1.%0111_1111_1111_1111+32,767,这是最大的16位正数。
2.%1000_0000_0000_0000所有位取反。
3.%1000_0000_0000_0001加1(8001h,即-32,767)。
然后是对16,384($4000)求负:
1.%0100_0000_0000_0000 16,384。
2.%1011_1111_1111_1111所有位取反($BFFF)。
3.%1100_0000_0000_0000加1($C000,即-16,384)。
最后是对-32,768($8000)求负:
1.%1000_0000_0000_0000-32,768,这是最小的16位负数。
2.%0111_1111_1111_1111所有位取反($7FFF)。
3.%1000_0000_0000_0000加1($8000,即-32,768)。
对$8000取反的结果为$7FFF,加1后得到了$8000!-(-32,768)等于-32,768,这是怎么回事?这显然不对。采用16位二进制补码的计数系统无法表示+32,768。通常,不能对二进制补码计数系统中的最小负值求负。