如何检测Java中的溢出功率

时间:2015-11-10 20:25:33

标签: java exception integer-overflow

我知道 java.lang.Math 提供了一组静态方法来执行某些操作(sumdifferencemultiply,{{1 }},incrementdecrementnegate),在溢出时抛出toInt

是否有类似的力量?

4 个答案:

答案 0 :(得分:9)

不,Java中内置的pow没有任何等效内容。 (Java中内置的唯一pow方法是Math.pow,它接受​​双精度并且不会以与整数相同的方式溢出,而BigInteger.pow则不会溢出,因为BigInteger s可以任意大。)

如果第三方库是可以接受的,那么,番石榴有例如IntMath.checkedPow,它会执行您正在寻找的内容。

答案 1 :(得分:4)

正如Chirag所说,整数在溢出时会抛出异常而双精度则不会。不要过于具体,但基本上,内存中的双倍存储非常类似于科学记数法,因为它们是一些整数* 2 ^(一些功率),因此永远不会真正溢出而是乘以这么大或小的2 ^(一些力量)他们完全失去了精确度。因此,您可以将双重溢出视为完全失去精确度,并打印为Infinity-Infinity

因此,您需要通过检查结果值是Double.POSITIVE_INFINITY还是Double.NEGATIVE_INFINITY来手动检查是否发生了溢出。

以下是一些展示我的意思的示例代码:

public static void main(String[] args) throws Exception
{
    double a = Double.MAX_VALUE; // highest possible double
    double b = Double.MAX_VALUE; // highest possible double

    if (Math.pow(a, b) == Double.POSITIVE_INFINITY || Math.pow(a, b) == Double.NEGATIVE_INFINITY)
    {
        throw new ArithmeticException("Double Overflow");
    }
}

答案 2 :(得分:1)

如果你自己的实现没问题,你可以这样做:

private static final int[] maxBaseForExponent = IntStream.range(0, 30)
        .map(e -> (int) Math.pow(Integer.MAX_VALUE, 1d / e)).toArray();

public static int powExact(int base, int exponent) {
    if (exponent < 0) {
        throw new ArithmeticException("Negative exponent");
    }
    if ((base < -1 || base > 1) && (exponent > 30 || base > maxBaseForExponent[exponent])
            && !(base == -2 && exponent == 31)) {
        throw new ArithmeticException("Overflow");
    }
    switch (base) {
    case -2:
        return (exponent & 1) == 0 ? 1 << exponent : -1 << exponent;
    case -1:
        return (exponent & 1) == 0 ? 1 : -1;
    case 0:
        return exponent == 0 ? 1 : 0;
    case 1:
        return 1;
    case 2:
        return 1 << exponent;
    default:
    }
    int result = 1;
    while (exponent != 0) {
        if ((exponent & 1) != 0) {
            result *= base;
        }
        exponent >>= 1;
        base *= base;
    }
    return result;
}

here获取算法,并使用包含每个指数0到30的最大基数的数组对其进行修改以检查溢出。

答案 3 :(得分:0)

整数只有32位。所以最大值是2 ^ 31 -1。 (如果使用BigInteger.pow。效率较低。) 因此,您可以手动检查并在需要时抛出异常 否则使用使用double的Math.pow