Integer溢出问题

0. 背景

在刷 LeetCode 时,代码的执行结果与预期出现了偏差,原因是 Int 值超过了允许范围 − 2 31 , 2 31 − 1 -2\^{31},2\^{31}-1 −231,231−1。工作中从来没有遇到过这种情况,之前的认知是如果 Int 中存储的值超过了允许范围也许代码会报错,又或者会自动截断。但是真实的结果却与预期的不同,Java 不但没有报错,也没有对 Int 值进行截断,而是 Int 值直接从一个边界跳转到另一个边界。

java 复制代码
//Int最大值 + 1 = Int最小值
Integer.MAX_VALUE + 1 = Integer.MIN_VALUE;
//Int最小值 -1 = Int最大值
Integer.MIN_VALUE - 1 = Integer.MAX_VALUE;

同时出现的另一个问题是,对 Integer.MIN_VALUE 使用 Math.abs 方法会失效,取出的绝对值居然还是负数,数值没有发生变化。

1. Integer 如何处理溢出的数据

Integer 的运算并不是使用十进制进行的,而是使用二进制补码进行的。 Integer 在 Java 中的定义是 4 个字节,1 个字节是 8 位,所以上限是 32 位( − 2 31 , 2 31 − 1 -2\^{31},2\^{31}-1 −231,231−1)。当 Integer 在运算过程中超出了 32 位,计算机会对改变量进行截断,将超出的部分(新增的最高位)进行舍弃。

java 复制代码
//Int 最小值 -1 = Int 最大值
Integer. MIN_VALUE - 1 = Integer. MAX_VALUE;

根据 Integer 对溢出情况的处理,对上述代码进行验算,验算过程如下,-1 相当于加上 -1。补码运算时符号位也是参与运算的。

2. 如何避免程序悄悄的发生 Integer 溢出

在程序运行中最可怕的不是程序报错,而是没有任何异常的情况下得到与预期不相符的结果。

使用 Math.addExact 和 Math.subtractExact 方法代替 + 和 -,Math.addExact 和 Math.subtractExact 方法会在出现溢出时抛出异常如下。

java 复制代码
Exception in thread "xxxx" java.lang.ArithmeticException: integer overflow
at java.base/java.lang.Math.addExact(Math.java:911)

可以通过对异常的处理捕获或处理让技术团队知道出现了 Integer 溢出。

3. 为什么 Math.abs 对 Integer.MIN_VALUE 无效

Math.abs 的源码如下,只是简单的对负数做了一个 - 操作,类似 * -1。

java 复制代码
public static int abs(int a) {  
    return (a < 0) ? -a : a;  
}

二进制中的相反数是对该数字安位取反(含符号位)后+1 。而通过计算得出 Integer.MIN_VALUE 的相反数等于它的本身,所以 Math.abs 对 Integer.MIN_VALUE 无效,计算过程如下。

原码---补码转换的计算过程可以参考这篇文档------原码、反码和补码。

二进制相反数的原理可以参考这篇文档------二进制相反数。

参考资料

JAVA 整数溢出问题
Java如何判断整数溢出,溢出后怎么得到提示
关于int的范围以及溢出问题
反码和补码的数学原理
由 Math.abs 谈负数转换与绝对值运算

相关推荐
木易 士心10 小时前
Java 后端驱动远程手机自动化:ADB + Python + 内网穿透实战全解
java·后端·智能手机·自动化
十年Java程序媛10 小时前
JVM 内存区域与对象内存布局|new 对象底层流程,对象头 MarkWord 详解
java·jvm·spring boot
用户0942485680310 小时前
第2章:Windows、WSL2 与 Docker 环境搭建Redis
java·jvm
小物学长10 小时前
HJ212-2017 对接与环境在线监测平台设计:报文、CRC、应答、预警和传输有效率
java
171320330计算机毕设编程10 小时前
计算机毕业设计 基于springboot+vue的在线观鸟视频播放网站 LW PPT
java·大数据·vue.js·spring boot·算法·课程设计
IT枫斗者枫哥10 小时前
JDBC事务实测:操作日志写入失败时,让客户修改一起回滚
java
OxYGC10 小时前
Spring 面经系列 · 第 1 篇:Bean 生命周期、单例语义、依赖注入与线程安全
java·安全·spring
小物学长10 小时前
Java 程序员的 IoT 协议入门(一):物联网平台到底在做什么
java
const_qiu10 小时前
第四章 07:4.7 本章小结
java·运维·服务器·人工智能