双精度或大十进制溢出吗?

2022-09-02 10:06:41

Java 8为我们提供了整数的Math.addExact(),但不是小数。

是否有可能溢出和溢出?通过Double.MAX_VALUEHow to get bigDecimal值来判断,我会说答案是肯定的。doubleBigDecimal

因此,为什么我们没有这些类型呢?我们自己检查这个问题的最可维护方法是什么?Math.addExact()


答案 1

double溢出到 和 ,它不会缠绕。 不会溢出,句号,它只受计算机内存量的限制。详见: 如何获得最大的大十进制值Infinity-InfinityBigDecimal

和 之间的唯一区别是,它尝试检测是否发生了溢出,并引发异常而不是换行。下面是源代码:+.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;
}

如果你想检查溢出是否已经发生,从某种意义上说,这样做会更简单,因为你可以简单地检查或 ;在 and 的情况下,这是一个稍微复杂一些的问题,因为它并不总是一个固定值,但在另一个固定值中,这些可能是输入(例如 在这种情况下,您可能不想引发异常)。doubleDouble.POSITIVE_INFINITYDouble.NEGATIVE_INFINITYintlongInfinity + 10 = Infinity

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


答案 2

您不需要浮点数字的函数的原因是,它不是环绕,而是溢出到 。addExactDouble.Infinity

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

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

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

BigDecimal另一方面,在这种情况下,确实溢出并引发相应的异常 - 这在实践中不太可能发生。


推荐