今天来说说Java中,数值的二进制格式是怎么样的。
?
如果你能很快的写出下面五条System out 的结果,那么,你可以不用继续看本博客了,因为你看下去也是浪费时间。^_^
?
?
class="java">int min = Integer.MIN_VALUE; int min2 = Integer.MIN_VALUE - 1; int max = Integer.MAX_VALUE; int max2 = Integer.MAX_VALUE + 1; System.out.println(-1 + " : " + Integer.toBinaryString(-1)); System.out.println(min + " : " + Integer.toBinaryString(min)); System.out.println(min2 + " : " + Integer.toBinaryString(min2)); System.out.println(max + " : " + Integer.toBinaryString(max)); System.out.println(max2 + " : " + Integer.toBinaryString(max2));
?
?
我们知道,Java中,int 型数据的是4个字节的,最大长度为 4*8 = 32.
而,int 是有符号类型的数据,所以,最高位的数值是用来表示正数或者负数的。1为负,0为正。
所以,对于int 型的最大值?Integer.MAX_VALUE 而言,它的二进制的格式,我们应该都能很快写出:
?
0111 1111 1111 1111 1111 1111 1111 1111
最高位的0,是用来表示这是一个正数。
?
既然?Integer.MAX_VALUE 已经是最大值了,那么,?Integer.MAX_VALUE + 1 应该等于什么呢?
下面我们就来算一下:
?
0111 1111 1111 1111 1111 1111 1111 1111 + 1 ----------------------------------------------- = 1000 0000 0000 0000 0000 0000 0000 0000
大家对这个算术结果都没问题吧?
那么,“1000 0000 0000 0000 0000 0000 0000 0000” 这个值是多少呢?下面进行说明。
首先,大家应该注意到,这个数字的最高位已经变成了“1”,所以,这个数已经变成了一个负数了。
那么,对于一个负数,它的值要怎么计算呢?
这个就要说到一个Java规范了:Java是基于2的补码算术来计算数值的,对于负数,则需要对每一位进行取反,最后加1,即得到数值。
根据这个规范,我们来计算一下“1000 0000 0000 0000 0000 0000 0000 0000” 的值:
1 000 0000 0000 0000 0000 0000 0000 0000 取反 1 111 1111 1111 1111 1111 1111 1111 1111 加1 1 ------------------------------------------------------ = 1 1000 0000 0000 0000 0000 0000 0000 0000
把最左边的符号位与其他的数据位隔了比较大的距离,这样看起来比较方便。
?
大家会发现,运算得到的值有 33 位了。
我们这样理解: 最高位(即最左边) 的1 是符号位,1 表示负值。其余的32位,值为 2^31。所以,结合起来看,“1 000 0000 0000 0000 0000 0000 0000 0000” 的值就是 -2^31
看到这,大家肯定都发现了,这个值就是?Integer.MIN_VALUE 的值。对的!!,所以?Integer.MIN_VALUE的二进制格式就是“”“1 000 0000 0000 0000 0000 0000 0000 0000”?。
?
既然?Integer.MAX_VALUE + 1 =?Integer.MIN_VALUE, 那么?Integer.MIN_VALUE -1 当然就等于Integer.MAX_VALUE ?喽。
?
上面说了,对于负数,Java是对各位进行取反加1计算得出值的,那么,我们现在,来反推一下 ?“-1” 这个数,在Java中,它对应的 二进制格式是什么样的。
如果,用原码表示,它应该是这样的:
1 000 0000 0000 0000 0000 0000 0000 0001
?既然Java在计算的时候,采取的是针对补码进行 “取反加1” 来计算的,那么,我们理所当然的会想到,对上面的原码进行“减1取反”来得到它的补码吧:
1 000 0000 0000 0000 0000 0000 0000 0001 减1 - 1 ------------------------------------------------ = 1 000 0000 0000 0000 0000 0000 0000 0000 取反 1 111 1111 1111 1111 1111 1111 1111 1111
?所以,Java中,“-1”的二进制格式当然就是:
11111111111111111111111111111111
?
?
好了,到此,应该可以给出本文最初的5个 System out 的输出了吧?它们就是:
?
-1 : 11111111111111111111111111111111 -2 : 11111111111111111111111111111110 -2147483648 : 10000000000000000000000000000000 2147483647 : 1111111111111111111111111111111 2147483647 : 1111111111111111111111111111111 -2147483648 : 10000000000000000000000000000000
?
?
题外话:对于数据的溢出,我是这么看的:
我一直把int的数据范围看成是一个环形,如下图。
最大值,往左一步(即,+1)就变成最小值;
最小值,往右一步(即,-1)就变成最大值
?
?
?
?