是否双精度或BigDecimal溢出



Java 8给了我们Math.addExact()来处理整数,而不是小数。

doubleBigDecimal是否可能溢出?根据Double判断。MAX_VALUE和如何获得最大的BigDecimal值我想说答案是肯定的。

因此,为什么我们不为这些类型也设置Math.addExact()呢?我们自己检查这一点的最可维护的方法是什么?

double溢出到Infinity-Infinity,不绕行。BigDecimal不会溢出,周期,它只受限于您的计算机内存量。参见:如何获取最大的BigDecimal值

+.addExact之间的唯一区别是它尝试检测是否发生溢出并抛出异常而不是包装。下面是源代码:

public static int addExact(int x, int y) {
    int r = x + y;
    // HD 2-12 Overflow iff both arguments have the opposite sign of the result
    if (((x ^ r) & (y ^ r)) < 0) {
        throw new ArithmeticException("integer overflow");
    }
    return r;
}

如果你想检查是否发生了溢出,从某种意义上说,使用double更简单,因为你可以简单地检查Double.POSITIVE_INFINITYDouble.NEGATIVE_INFINITY;在intlong的情况下,这是一个稍微复杂的问题,因为它并不总是一个固定值,但在另一个,这些可能是输入(例如Infinity + 10 = Infinity,你可能不想在这种情况下抛出异常)。

由于所有这些原因(我们甚至还没有提到NaN),这可能就是为什么这样的addExact方法在JDK中不存在的原因。当然,您总是可以在自己的应用程序中将自己的实现添加到实用程序类中。

对于浮点数不需要addExact函数的原因是,它不是绕行,而是溢出到Double.Infinity

因此,您可以非常容易地在操作结束时检查是否溢出。由于Double.POSITIVE_INFINITY + Double.NEGATIVE_INFINITY是NaN,您还必须在更复杂的表达式的情况下检查NaN。

这不仅更快,而且更容易阅读。而不是让Math.addExact(Math.addExact(x, y), z)将3个双精度加在一起,你可以这样写:

double result = x + y + z;
if (Double.isInfinite(result) || Double.isNan(result)) throw ArithmeticException("overflow");
另一方面,

BigDecimal 在这种情况下也会溢出并抛出相应的异常——尽管这在实践中不太可能发生。

double请核对其他答案

BigDecimal已经内置了addExact()保护。BigDecimal的许多算术运算方法(例如multiply)包含对结果比例的检查:

private int checkScale(long val) {
    int asInt = (int)val;
    if (asInt != val) {
        asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        BigInteger b;
        if (intCompact != 0 &&
            ((b = intVal) == null || b.signum() != 0))
            throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow");
    }
    return asInt;
}

最新更新