由 -128 引发的思考

  对于 8 位的有符号数而言,它的范围在 -128~127。该数的范围若在 -127~127,那还好理解,但关键该数还可取值 -128。那 -128 是怎么来的呢?

-128 的来源

说法一

  有人就说了,8 位的有符号数除了表示 -127~127,还剩下一个二进制数 “1000 0000B”没有用,这太浪费了,所以用来表示 -128。这种说法很明显是站不住脚的。原因主要有两个:1)既然浪费,那该二进制数也可用来表示除了 -128 之外的数;2)数学是一门严谨的语言,不存在如此模糊的说法。

说法二

  还有一个说法,来自百度文库的一篇文章,即作者通过如下的列举法:

正数:补码跟原码一样
+127, 0111 1111
+126, 0111 1110
+125, 0111 1101
+124, 0111 1100
+123, 0111 1011
+122, 0111 1010
...
+4,   0000 0100
+3,   0000 0011
+2,   0000 0010
+1,   0000 0001
0,    0000 0000 (无正负之分)

负数:
值     原码       反码        补码
-1,   1000 0001, 1111 1110, 1111 1111
-2,   1000 0010, 1111 1101, 1111 1110
-3,   1000 0011, 1111 1100, 1111 1101
-4,   1000 0100, 1111 1011, 1111 1100
-5,   1000 0101, 1111 1010, 1111 1011
-6,   1000 0110, 1111 1001, 1111 1010
-7,   1000 0111, 1111 1000, 1111 1001
-8,   1000 1000, 1111 0111, 1111 1000
-9,   1000 1001, 1111 0110, 1111 0111
-10,  1000 1010, 1111 0101, 1111 0110
-11,  1000 1011, 1111 0100, 1111 0101
-12,  1000 1100, 1111 0011, 1111 0100
-13,  1000 1101, 1111 0010, 1111 0011
-14,  1000 1110, 1111 0001, 1111 0010
-15,  1000 1111, 1111 0000, 1111 0001
-16,  1001 0000, 1110 1111, 1111 0000
-17,  1001 0001, 1110 1110, 1110 1111
...
-24,  1001 1000, 1110 0111, 1110 1000
...
-99,  1110 0011, 1001 1100, 1110 0100
...
-124, 1111 1100, 1000 0011, 1000 0100
-125, 1111 1101, 1000 0010, 1000 0011
-126, 1111 1110, 1000 0001, 1000 0010
-127, 1111 1111, 1000 0000, 1000 0001

按照规律, -127 的补码再往下应该还有补码 “1000 0000”,该二进制数表示 -128。 

  作者的列举法看起来确实形象了许多,但却仍未能够解释根本的数学原理。

说法三

  这种说法是个人的想法,不过跟说法二一样,都是为了解释而解释。

  我们知道 -128 = -127 - 1,那我们就可以通过 -127 和 -1 的相加得到 -128 的补码了。而 -127 的补码为 1000 0001,-1 的补码为 1111 1111,两者相加得到的结果是 1 1000 0000。因为只有 8 位可表示,所以我们可以舍掉补码最高位 1,剩下的就表示 -128 的补码了,也即 -128 的补码为 1000 0000。

  这种说法就更加问题多多,而且还牵扯到了溢出问题。

说法四

  最靠谱的说法一定是来自严格的数学推导或定理。

  一般而言,在计算机中对有符号数的表示方式采用的是 Two's complement (实际上就是补码)方法。它的数学公式如下:

  

  这样我们很容易就可以得到下边几个例子:

  

  同理可以得到:

  

  这样补码 “1000 0000” 表示 -128 的问题就可以解决了。我们因此知道,对于有 w 位补码(不是原码或反码),它能够表示的范围在:

  当然,用补码来计算我们得保证其运算过程的正确性。这方面可参考《深入理解计算机系统》第 2 章“信息的表示和处理”的第 2.3 节“整数运算”。

-128 + 127 = -1 ?

  在实际研究中,还遇到一些感觉很奇怪的问题,例如 -128 加上 127 应该等于多少。我们从上文已经知道 -128 的补码是 1000 0000,而 127 的补码是 0111 1111,那 -128+127 的结果用补码表示就是 1111 1111。在思维没有切换到原码之前,总是将 1111 1111 当做 -127,而没有将其由补码转化为原码,从而导致理解上的错误。

  所以,得时刻记住下图:

  

 

posted @ 2015-12-20 19:55  峰子_仰望阳光  阅读(375)  评论(0编辑  收藏  举报