Как обнаружить переполнение на power в Java

Я знаю, что java.ленг.Математика!--10--> предоставляет набор статических методов для выполнения некоторых операций (sum, difference, multiply, increment, decrement, negate, toInt), выбрасывание ArithmeticException при переполнении.

есть ли что-то подобное для власти?

4 ответов


нет, нет ничего эквивалента pow встроенный в Java. (Единственное pow методы, встроенные в Java являются Math.pow, который принимает удвоения и не переполняется так же, как целые числа, и BigInteger.pow, который не переполняется, потому что BigIntegers может быть произвольно большим.)

если сторонние библиотеки приемлемы, хотя, Guava имеет, например,IntMath.checkedPow, который делает то, что вы ищете.


As Чираг сказал, чисел генерируют исключения при переполнении пока двойников нет. Чтобы не получить слишком специфические, но, в основном, двухместные номера в памяти хранятся очень похоже на экспоненциальном представлении, в том, что они какое-то число * 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");
    }
}

Если это нормально иметь свою собственную реализацию, вы могли бы сделать что-то вроде этого:

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;
}
алгоритм здесь, и изменил его, чтобы проверить переполнение, используя массив, который содержит максимальную базу для каждого показателя от 0 до 30.

целые числа составляют всего 32 бита. поэтому максимальное значение-2^31 -1. ( При использовании BigInteger.pow. Это менее эффективно.) Таким образом, вы можете проверить вручную и при необходимости создать исключение еще используйте Math.pow который использует double.