Java int 范围 -2147483648 ~ 2147483647
执行一下代码发现:
int a = 2147483647; int b = a + 1; int c = b - 1; sout(b) // b = -2147483648 sout(c) // c = 2147483647
b 是 -2147483648
c 是 2147483647
似乎是一个循环?
为什么原码反码补码
上边这个链接看完知道,cpu二进制计算不对原码进行计算, 而是对补码进行计算。
就是说计算机的运算方式并不完全是按照人类的计算方式来的即 1+1有时候不是等于2
其实应该是初学时就应该研究的问题。只是在学校没好好学
在这个基础上
补码运算| 十进制 | 八进制 | 原码 | 补码 |
|---|---|---|---|
| 2147483647 | 7FFFFFFF | 0111 1111 1111 1111 1111 1111 1111 1111 | 0111 1111 1111 1111 1111 1111 1111 1111 |
| 1 | 1 | 0000 0000 0000 0000 0000 0000 0000 0001 | 0000 0000 0000 0000 0000 0000 0000 0001 |
| -1 | FFFFFFFF | 1000 0000 0000 0000 0000 0000 0000 0001 | 1111 1111 1111 1111 1111 1111 1111 1111 |
| -2147483647 | 80000001 | 1111 1111 1111 1111 1111 1111 1111 1111 | 1000 0000 0000 0000 0000 0000 0000 0001 |
| -2147483648 | 80000000 | 32位无法表示 | 1000 0000 0000 0000 0000 0000 0000 0000 |
1. 首位为符号位 “0 - 正”, “ 1 - 负”
2. 正数的补码就是它本身
3. 负数的补码是 原码符号位不变,各位取反,末尾加1
回到开始的发现
java中 int 是 32位 ,也就是说最多最多可以保存二进制32位,如果计算所过程中超出这个范围那么计算机的计算方式就与人类不同,即可能发生 1+1不等于2的问题.
这里的范围看JAVA Integer.java 源码
@Native public static final int MIN_VALUE = 0x80000000;
@Native public static final int MAX_VALUE = 0x7fffffff;
转成补码的意义对于计算机来说就是,只有 加 运算
比如 1 - 1 就是:1 的补码加上 -1 的补码
32位运算, 即:
0000 0000 0000 0000 0000 0000 0000 0001
+
1111 1111 1111 1111 1111 1111 1111 1111=
1 0000 0000 0000 0000 0000 0000 0000 0000
只能保存 32bit 的数据,所以 1 被丢弃
上式=
0000 0000 0000 0000 0000 0000 0000 0000
这样计算机就可以仅通过加法且忽略符号直接计算出结果
明白了这些,现在再计算一下 JAVA 中 int 的 2147483647 + 1
首先两者转换成二进制原码,然后得出其补码,正数的补码是他本身
即:
0111 1111 1111 1111 1111 1111 1111 1111
+
0000 0000 0000 0000 0000 0000 0000 0001=
1000 0000 0000 0000 0000 0000 0000 0000
这个数字就非常特别了,把它当作一个补码,转换成原码:
首位符号位不变,其余位置取反,
1111 1111 1111 1111 1111 1111 1111 1111
末尾加1
1 0000 0000 0000 0000 0000 0000 0000 0000
舍掉溢出的部分
0000 0000 0000 0000 0000 0000 0000 0000
好像就是 0,但计算机并不关心原码,所有运算和存储都是补码。
所以简单来说计算机把这个数字当作人类认为的 -2147483648
可以这样来说:
-2147483647 的补码是 1000 0000 0000 0000 0000 0000 0000 0001
而这个补码并不是 32位可以存储的最小数字,即它还可以 减一
计算机存储的是 1000 0000 0000 0000 0000 0000 0000 0000
我们理解的是 -2147483648
那么,最后再计算一个 -2147483648 -1
即,
-2147483648 + (-1)
=
1000 0000 0000 0000 0000 0000 0000 0000
+
1111 1111 1111 1111 1111 1111 1111 1111=
1 0111 1111 1111 1111 1111 1111 1111 1111
最高位溢出,舍掉=
0111 1111 1111 1111 1111 1111 1111 1111
那么,最高位是0 是正数,正数的原码和补码一致,所以他的十进制数就是:2147483647
破案了
也就是说,由于存储位数的限制,int 类型的数据被设计成只能存储二进制32bit的数据,所以当计算的结果超过的这个范围时(2147483647 +1或-2147483648 -1)由于更高一位的数据被丢弃,所以此时计算机的运算并不符合人类的运算逻辑。
解释了为什么 int自增运算 似乎是一个循环的问题。
以上为个人理解的思路,在查资料过程中发现已经有大神详细的说明了此处的疑惑:-2147483648~2147483647–深入计算机内存运算了解二进制本质



