一个字节表示的有符号整数范围为什么是[-128, 127]

首先计算机只会加法, 所以减运算会被替换为加运算, 即:
5 - 2 = 5 + (-2)

模的性质: 以时钟为例, 12个小时时针走一圈, 12便是时钟的模, 倘若时针当前指向的数字是8, 减3个小时那么时针指向的数字就是5; 但是加上9个小时时针指向的位置也是5, 因为3和9在12这个模上是互补的(3 + 9 = 12), 所以-3跟+9的效果是一样的. 即减一个数字跟加一个与此数字在模上的补数最后结果是相同的.

以一个字节(8位)的大小为例, 在不设符号位的情况下可表示的范围是00000000 ~ 11111111, 即[0, 255]共256个数, 所以一个字节的模是256.
根据上面所说, 5 + (-2) 就等价于 5 + (256 -2) = 5 + 254
5 ( 2 ) 5_{(2)}5(2) = 0000 0101
25 4 ( 2 ) 254_{(2)}254(2) = 1111 1110
两者相加去掉溢出位得到0000 0011 = 3, 刚好是5 - 2的结果

有符号数在计算机内存里面是以补码的形式存在并参与运算的, 为什么要这么做呢, 看上面的例子, -2的补码刚好就是254的二进制表示, 补码补码, 表示的就是在当前模下的补数的二进制. 所以计算机在进行运算时其实是将符号位一起参与运算, 最高位为符号位, 正数为0, 负数为1; 正数原码补码都相同(正数的补码仅仅是为了统一概念), 负数补码为原码取反再加1. 所有的这些规则都是为了统一正数与负数间的计算:
5 ( 补 ) 5_{(补)}5() = 0000 0101
− 2 ( 补 ) -2_{(补)}2() = 1111 1110
两者相加得到0000 0011, 刚好就是结果3的补码

在补码里面, 1000 0000比较特殊, 对它再求一次补得到0000 0000, 但是0的补码是0000 0000, 有符号数的原码里面有两个0, 正0: 00000000, 负0: 1000 0000, 它们俩的补码都是0000 0000, 刚好统一. 所以补码1000 0000的原码不存在, 或者说无意义. 但是-127 - 1与127 + 1的运算结果(补码形式)都是1000 0000, 所以1000 0000既可以表示-128的补码也可以表示128的补码, 二选一. 但是为了统一最高位符号位为1就是负数这一概念, 就将1000 0000定为-128的补码, 而不是正的128. 所以一个字节的表示范围就是[-128, 127].


版权声明:本文为weixin_46364491原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。