栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

奇怪的 -2147483648;为什么Java中 2147483647加一是-2147483648

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

奇怪的 -2147483648;为什么Java中 2147483647加一是-2147483648

发现

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
其实应该是初学时就应该研究的问题。只是在学校没好好学

在这个基础上

补码运算
十进制八进制原码补码
21474836477FFFFFFF0111 1111 1111 1111 1111 1111 1111 11110111 1111 1111 1111 1111 1111 1111 1111
110000 0000 0000 0000 0000 0000 0000 00010000 0000 0000 0000 0000 0000 0000 0001
-1FFFFFFFF1000 0000 0000 0000 0000 0000 0000 00011111 1111 1111 1111 1111 1111 1111 1111
-2147483647800000011111 1111 1111 1111 1111 1111 1111 11111000 0000 0000 0000 0000 0000 0000 0001
-21474836488000000032位无法表示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–深入计算机内存运算了解二进制本质

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/667078.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号