博客
关于我
Java——如何判断整数溢出
阅读量:797 次
发布时间:2023-03-28

本文共 2404 字,大约阅读时间需要 8 分钟。

如何检测整数相加是否溢出并处理

在编程中,处理整数溢出的问题是非常重要的,尤其是在执行加法、减法和乘法操作时。Java中的整数类型有固定的范围,int的范围是从-2^31到2^31-1。溢出会导致意外的结果,因此需要检测并处理溢出情况。

在本文中,我们将探讨如何检测int相加后是否溢出,并在溢出时返回Integer.MAX_VALUE。我们还将讨论减法和乘法的溢出检测方法。


加法溢出检测

对于加法操作,我们可以使用位运算来检测溢出。具体来说,我们可以检查x和y的和是否导致符号位发生变化。

代码实现

public static int addExact(int x, int y) {    int r = x + y;    if (((x ^ r) & (y ^ r)) < 0) {        throw new ArithmeticException("integer overflow");    }    return r;}

代码解释

  • 计算和:首先,计算x和y的和,结果存储在变量r中。
  • 检查符号位变化:通过位运算检测x和y的和r的符号是否与x和y的符号不同。具体来说,检查(x ^ r)和(y ^ r)的按位与是否小于0。如果小于0,说明符号发生了变化,可能发生溢出。
  • 抛出异常:如果检测到符号变化且r不为0,抛出ArithmeticException异常,表示整数溢出。
  • 返回结果:如果没有溢出,返回结果r。
  • 这个方法有效地检测了加法溢出,并且在溢出时正确处理了异常。


    减法溢出检测

    对于减法操作,检测溢出的逻辑与加法类似,但需要考虑减法的特殊性。

    代码实现

    public static int subtractExact(int x, int y) {    int r = x - y;    if (((x ^ r) & (y ^ r)) < 0) {        throw new ArithmeticException("integer overflow");    }    return r;}

    代码解释

  • 计算差:首先,计算x减去y的差,结果存储在变量r中。
  • 检查符号位变化:通过位运算检测x和y的差r的符号是否与x和y的符号不同。具体来说,检查(x ^ r)和(y ^ r)的按位与是否小于0。
  • 抛出异常:如果检测到符号变化且r不为0,抛出ArithmeticException异常,表示整数溢出。
  • 返回结果:如果没有溢出,返回结果r。
  • 这个方法同样有效地检测了减法溢出,并且在溢出时正确处理了异常。


    乘法溢出检测

    对于乘法操作,检测溢出的逻辑需要考虑乘法的性质,并且可以使用不同的方法来处理。

    int乘法溢出检测

    public static int multiplyExact(int x, int y) {    long r = (long)x * (long)y;    if ((int)r != r) {        throw new ArithmeticException("integer overflow");    }    return (int)r;}

    代码解释

  • 计算乘积:将x和y转换为long类型,计算它们的乘积,结果存储在变量r中。
  • 检查溢出:将结果r转换回int类型,如果转换后与原值不一致,说明发生了溢出。
  • 抛出异常:如果发生溢出,抛出ArithmeticException异常。
  • 返回结果:如果没有溢出,返回转换后的int结果。
  • 这个方法利用了long的范围来避免int溢出,并通过转换检查是否溢出。

    long乘法溢出检测

    对于long乘法,检测溢出的逻辑稍微复杂一些,但可以通过检查乘积的绝对值是否超过long的范围来实现。

    public static long multiplyExact(long x, long y) {    long r = x * y;    long ax = Math.abs(x);    long ay = Math.abs(y);    if (((ax | ay) >>> 31 != 0)) {        // Some bits greater than 2^31 that might cause overflow        // Check the result using the divide operator        // and check for the special case of Long.MIN_VALUE * -1        if (((y != 0) && (r / y != x)) || (x == Long.MIN_VALUE && y == -1)) {            throw new ArithmeticException("long overflow");        }    }    return r;}

    代码解释

  • 计算乘积:计算x和y的乘积,结果存储在变量r中。
  • 检查绝对值:计算x和y的绝对值,并检查它们是否超过了long的范围的一半(2^31)。
  • 特殊情况检查:如果乘积的绝对值超过了范围,进一步检查乘积是否与原始值一致,或者是否在Long.MIN_VALUE和-1的情况下发生溢出。
  • 抛出异常:如果检测到溢出,抛出ArithmeticException异常。
  • 返回结果:如果没有溢出,返回乘积结果r。
  • 这个方法通过位运算和除法操作来检测长整数溢出,确保了正确性。


    总结

    在本文中,我们探讨了如何检测int、long等不同类型的整数溢出,并提供了相应的解决方案。通过使用位运算和数学检查,我们可以有效地检测溢出,并在必要时抛出异常。

    如果您对这些方法有任何疑问或需要进一步的帮助,请随时联系!

    转载地址:http://flhfk.baihongyu.com/

    你可能感兴趣的文章
    OpenCV与AI深度学习 | 实战 | 使用YOLOv8 Pose实现瑜伽姿势识别
    查看>>
    OpenCV与AI深度学习 | 实战 | 使用YoloV8实例分割识别猪的姿态(含数据集)
    查看>>
    OpenCV与AI深度学习 | 实战 | 使用姿态估计算法构建简单的健身训练辅助应用程序
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于OpenCV和K-Means聚类实现颜色分割(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于YoloV5和Mask RCNN实现汽车表面划痕检测(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于YOLOv9+SAM实现动态目标检测和分割(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于YOLOv9和OpenCV实现车辆跟踪计数(步骤 + 源码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 文本图片去水印--同时保持文本原始色彩(附源码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 通过微调SegFormer改进车道检测效果(数据集 + 源码)
    查看>>
    OpenCV与AI深度学习 | 实战—使用YOLOv8图像分割实现路面坑洞检测(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战篇——基于YOLOv8和OpenCV实现车速检测(详细步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战|OpenCV实时弯道检测(详细步骤+源码)
    查看>>
    OpenCV与AI深度学习 | 实用技巧 | 使用OpenCV进行模糊检测
    查看>>
    OpenCV与AI深度学习 | 实践教程|旋转目标检测模型-TensorRT 部署(C++)
    查看>>
    OpenCV与AI深度学习 | 工业缺陷检测中数据标注需要注意的几个事项
    查看>>
    OpenCV与AI深度学习 | 干货 | 深度学习模型训练和部署的基本步骤
    查看>>
    OpenCV与AI深度学习 | 手把手教你用Python和OpenCV搭建一个半自动标注工具(详细步骤 + 源码)
    查看>>
    OpenCV与AI深度学习 | 水下检测+扩散模型:或成明年CVPR最大惊喜!
    查看>>
    OpenCV与AI深度学习 | 深度学习检测小目标常用方法
    查看>>
    OpenCV与AI深度学习 | 超越YOLOv10/11、RT-DETRv2/3!中科大D-FINE重新定义边界框回归任务
    查看>>