补码
由来
补码的概念,存在于整数的存储中,包括 int、short、long、char(由于char是用ASCII码存储在内存中,因此可以看作1字节的整数)等。
浮点数的存储思路与整数不同,并且十分复杂,本篇不赘述。
有符号的整型变量无论有多少个字节,第一个bit(第一个比特位)都作为符号位存储,0 表示整数,1 表示负数,然后剩下的bit用来存储数据。这里以 int 为例:
符号位 | 数据 |
---|---|
1位 | 31位 |
这样我们可以得到数字的原码。如 int -1 的原码:
10000000 00000000 00000000 00000001
由于计算机底层的加减法计算需要,人们又发明了反码与补码。反码与补码的变化只存在于负数中,整数的原码、反码、补码相同。反码就是除了符号位,剩下的位全部取反。那么 -1 的反码就是:
11111111 11111111 11111111 11111110
而补码就是反码 + 1。可以得到:
11111111 11111111 11111111 11111111
这便是 - 1 在内存中存储的方式。可以用代码验证下:
可以看到完全正确。
变量的取值范围
由此我们可以又补码理清整型变量的存储规律以及取值范围了。以1字节为例:
这便是1字节整数的取值。注意黄色行,1000 0000是-128,或许联系前后文可以想当然,但是如果我们要去计算它的反码与补码,就会发现计算不出。反码为补码减一,而数据位全为 0,借 1 只能向符号位借,而这是不可理喻的。倘若向符号位借了 1,就会出现这样的结果:
反码:0111 1111
原码:0000 0000
可以看到结果是 0。而原来符号位上是 1,因此是个负数,由此便得到了 -0。而表格的末尾就是 +0 了。这样重复显然是浪费。作为无效值就不如作为特殊值,这样还能多存储一个数字。所以,计算机规定, 1000 0000 这个特殊的补码就表示 -128。
其次,我们再按照“传统”的方法计算一下 -128 的补码:
-128 的数值位的原码是 1000 0000,共八位,而 char