Как обнаружить переполнение на power в Java
Я знаю, что java.ленг.Математика!--10--> предоставляет набор статических методов для выполнения некоторых операций (sum
, difference
, multiply
, increment
, decrement
, negate
, toInt
), выбрасывание ArithmeticException
при переполнении.
есть ли что-то подобное для власти?
4 ответов
нет, нет ничего эквивалента pow
встроенный в Java. (Единственное pow
методы, встроенные в Java являются Math.pow
, который принимает удвоения и не переполняется так же, как целые числа, и BigInteger.pow
, который не переполняется, потому что BigInteger
s может быть произвольно большим.)
если сторонние библиотеки приемлемы, хотя, 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.