欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > java >内容正文

java

【Java】System.out.println(Integer.MAX_VALUE+1);背后的二进制故事与启示

发布时间:2025/3/15 java 48 豆豆
生活随笔 收集整理的这篇文章主要介绍了 【Java】System.out.println(Integer.MAX_VALUE+1);背后的二进制故事与启示 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

导言

【说明】这里的代码用Java语言描述,工具为Jshell,但原理是通用的。

迷幻语句送上—— System.out.println(Integer.MAX_VALUE+1);

执行结果是什么?

Show me the answer……

OK……Look……

真是这个!!

原理分析

这个就要分析二进制了,我其实懒得在博客里分析一堆二进制,但这次我们看一下(大佬们可以略过~~)

先从二进制入手~~
(不讲如何转化原码、反码、补码,这个都不会的话肯定不是程序员甚至可以说没学过计算机……)

下图为+2147483647(32位,2^31-1,int上限):

这是正数哦,原码、反码、补码都是这个……

我们再看+1的:

相加,限于32位,会生成:

注意,这是补码,所以说我们就想到了二进制中的“怪异数”,所以判定这个数的真值是2^(-31),也就是-2147483648。

用long就不溢出了吧?

尽管int只有32位,而long是64位,但——

答案是:No!

别急,我们接着看:

为什么long也会溢出呢?

代码是这么执行的:
int类型的Integer.MAX_VALUE+1,计算结果其实还是int类型的,这时将int转型为long,瞬间扩到64位,但long会保留int本身的值,即符号位从32位移到64位,其余的第63位到第32位挂0。

要不然,如果符号位不移动,岂不是负数变正数,即下面的不是-4?显然不可能,扩容总不能丢失数据吧……

Integer.MAX_VALUE+2呢?

好吧,我们再做一遍二进制加法呗~~

我们姑且先认为是+1+1吧(这么算在这里比较方便),

基于+1的结果,-2147483648:

+1的二进制:

加法后:

这是补码诶,转反码:

转原码:

我们知道了,是-(2^(-31)-1),即-2147483647,符合十进制运算,下面验证一下:

好了,你说的我都懂,怎么能不变负数?

Good Question!

其实不难,在溢出之前转成long就行~~

这样就OK,嘿嘿……

你说的我懂了,问题是这东西有用?

有的,亲~~

我们的程序在运行的时候,比如说

int i = 1000000; System.out.println(i*i);

换成long:

这不是我们需要的答案啊!

那我们在能预判到的时候,就应该直接在运算前(可能溢出前)转型!!!

这就是我们要的~~

要注意什么……

我觉得主要是要注意在报错之前自己对数值大小有个预判,比较熟练地了解Integer.MAX_VALUE和Long.MAX_VALUE的十进制和二进制,能做一个大致的判断,若有溢出之嫌,可提前转型。

BigInteger呢?

另,BigInteger的话,超大容量:

可惜构造器好用的不多:

简单使用我觉得String类型参数就很好使……

可以用Integer和Long的包装类对象toString()进行转化,nice!!

总结

以上是生活随笔为你收集整理的【Java】System.out.println(Integer.MAX_VALUE+1);背后的二进制故事与启示的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。