您的位置:首页 > 编程语言 > Java开发

Java 的数值是怎么存储的

2016-01-14 17:15 323 查看
今天来说说Java中,数值的二进制格式是怎么样的。

如果你能很快的写出下面五条System out 的结果,那么,你可以不用继续看本博客了,因为你看下去也是浪费时间。^_^

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)就变成最大值

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: