计算机都是用二进制存储数据,这些二进制数值有两种格式表示:无符号数和有符号数。
以一个字节举例,byte=1个字节 = 8bit(位):
原码(true form)是一种计算机中对数字的二进制定点表示方法。数值最高位表示符号位:正数该位记为0,负数该位记为1(0有两种表示:+0和-0),其余位表示数值的大小。
举例:10进制的数值2和-2,我们用2进制来表示:
可以看出byte扣除了最高位的符号位,只剩7位二进制数能表示数值。它的最大值为:0111 1111,最小值为:1000 0000(这里其实用的是补码),即byte只能表示-128~127。
思考:
让我们带着问题继续往下阅读。
反码的表示方法是:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
举例:
补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1(即在反码的基础上+1)。
举例:
问题:
答:虽然人脑更容易识别原码、计算原码,但是计算机的二进制数值却是以补码的方式存在的,最终转换成原码给我们呈现。
具体分析:
这样存储的好处是避免的0的编码有两个,0000 0000原码和1000 0000原码都表示0,-0和+0;
并且,对于计算机来说,辨别"符号位"显然会让计算机的基础电路设计变得十分复杂。符号位和具体数值值位可以一起处理,减法通过加法就可以实现:1-1 = 1 + (-1) = 0,这样简化了计算机的结构设计,同时也提高了运算速度。
首先来看原码的减法计算:
1 - 1 = 1 + (-1) =
0000 0001原码 + 1000 0001原码 =
1000 0010原码 = -2
如果用原码表示,让符号位也参与计算,显然对于减法来说结果是不正确的,这也就是为何计算机内部不使用原码表示一个数。
为了解决原码做减法的问题,我们使用反码计算:
1 - 1 = 1 + (-1) =
0000 0001原码 + 1000 0001原码=
0000 0001反码 + 1111 1110反码 =
1111 1111反码 =
1000 0000原码 = -0
可以看到,我们用反码计算减法,结果的非符号位部分是正确的。唯一的问题出在于"0"这个特殊的数值上。虽然人们理解上+0和-0是一样的,但再计算机中0带符号是有意义的,并不是说0000 0000原码和1000 0000原码都表示0。
我们用0000 0000表示0,就不会出现-0的情况了,并且我们就可以用 1000 0000表示-128,如下公式所示:
(-1) + (-127) =
1000 0001原码 + 1111 1111原码 =
1111 1111补码 +1000 0001原码 =
1000 0000补码=-128
我们用以前的-0的补码来表示-128,所以-128并没有原码和反码表示。byte的取值范围是-128~127[-27, 27-1],你明白了吗?
举一反三:
32位的int表示范围:[-231, 231-1],即二进制表示范围:1000 0000 0000 0000 0000 0000 0000 0000~0111 1111 1111 1111 1111 1111 1111 1111
我们只说明了补码的计算,但这个规律是怎么发现的?这里面蕴含怎样的数学原理,这就触及到我的知识盲区了。