为什么Java的int取值范围是-2^31~ 2^31 -1
(-2147483648 ~ 2147483647
)
而不是-2147483647 ~ 2147483647
?
为什么C的int取值范围是-2^15 ~ 2^15 -1
(-32768 ~ 32767
)
而不是-32767 ~ 32767
?
以Java为例,Java的int占用空间为4字节
,即32Bit
,32个二进制位,其中有一位用于存储符号,0表示正,1表示负。(C语言int占空间为2字节
,16Bit
,同样有一位留给符号)
于是,正数的最大值很容易得到,
0111 1111 1111 1111 1111 1111 1111 1111
共有31位1 于是得到 2^31 -1
(=2^0 + 2^1 + … + 2^30),即2147483647
。
而数字0(+0)的表示方式为:
0000 0000 0000 0000 0000 0000 0000 0000
即32位0。
按照这种方式,不加改进的话,Java中int最小值就是:
1111 1111 1111 1111 1111 1111 1111 1111
即32位1,也就是: -2147483647
。
==================================================
但是,这种方式存在一种浪费情况,也就是 0同学一人占了两坑
1000 0000 0000 0000 0000 0000 0000 0000
同样也会表示了0(-0)
,这样0
脚踏两只船,很明显有点过分了。
于是为了将后者(也就是-0
的表达方式)利用起来,研究者们规定使用“补码”这一方法:
(引用自百度百科 补码)
- 正整数的补码是其二进制表示,与原码相同,就是保持现状,不做改变;
- 求负整数的补码,将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1。
同一个数字在不同的补码表示形式中是不同的。
比如-15的补码,在8位二进制中是11110001,然而在16位二进制补码表示中,就是1111111111110001。以下都使用8位2进制来表示。
【例】求-5的补码。
-5对应正数5(00000101)→所有位取反(11111010)→加1(11111011)
所以-5的补码是11111011。
【例】数0的补码表示是唯一的。
[+0]补=[+0]反=[+0]原=00000000
[ -0]补=11111111+1=00000000
这样,0只剩下了一种表达方式,腾出了一个坑位,所以,可以比原本的方式多表达一个值。
很幸运,Java中的 -2^31 (-2147483648
) 和C语言中的 -2^15 (-32768
)抓住了这个来之不易的机会,出现在了历史的舞台之上。