В моем маленьком проекте мне нужно сделать что-то вроде Math.pow (7777.66, 5555.44) только с ОЧЕНЬ большими числами. Я нашел несколько решений:
Кто-нибудь знает библиотеку или простое решение? Я полагал, что многие люди имеют дело с той же проблемой ...
пс Я нашел какую-то библиотеку под названием ApFloat, которая утверждает, что делает это приблизительно, но полученные результаты были настолько приблизительными, что даже 8 ^ 2 дало мне 60 ...
Решение для аргументов ниже 1.7976931348623157E308 (Double.MAX_VALUE), но поддерживающее результаты с МИЛЛИОНАМИ цифр:
Так как double поддерживает числа до MAX_VALUE (например, 100! в double выглядит как это: 9.332621544394415E157), нет проблем с использованием BigDecimal.doubleValue(). Но вы не должны просто делать Math.pow(double, double), потому что, если результат больше, чем MAX_VALUE, вы просто получите бесконечность. ТАК: используйте формулу X ^ (A + B) = X ^ A * X ^ B, чтобы разделить вычисление на ДВЕ степени: большую, используя BigDecimal.pow, и маленькую (остаток второго аргумента), используя Math. пау, тогда умножай. X будет скопировано в DOUBLE — убедитесь, что оно не больше MAX_VALUE, A будет INT (максимум 2147483647, но BigDecimal.pow в любом случае не поддерживает целые числа больше миллиарда), а B будет двойным, всегда меньше 1. Таким образом, вы можете сделать следующее (игнорировать мои личные константы и т.д.):
int signOf2 = n2.signum();
try {
// Perform X^(A+B)=X^A*X^B (B = remainder)
double dn1 = n1.doubleValue();
// Compare the same row of digits according to context
if (!CalculatorUtils.isEqual(n1, dn1))
throw new Exception(); // Cannot convert n1 to double
n2 = n2.multiply(new BigDecimal(signOf2)); // n2 is now positive
BigDecimal remainderOf2 = n2.remainder(BigDecimal.ONE);
BigDecimal n2IntPart = n2.subtract(remainderOf2);
// Calculate big part of the power using context -
// bigger range and performance but lower accuracy
BigDecimal intPow = n1.pow(n2IntPart.intValueExact(),
CalculatorConstants.DEFAULT_CONTEXT);
BigDecimal doublePow =
new BigDecimal(Math.pow(dn1, remainderOf2.doubleValue()));
result = intPow.multiply(doublePow);
} catch (Exception e) {
if (e instanceof CalculatorException)
throw (CalculatorException) e;
throw new CalculatorException(
CalculatorConstants.Errors.UNSUPPORTED_NUMBER_ +
"power!");
}
// Fix negative power
if (signOf2 == -1)
result = BigDecimal.ONE.divide(result, CalculatorConstants.BIG_SCALE,
RoundingMode.HALF_UP);
Примеры результатов:
50!^10! = 12.50911317862076252364259*10^233996181
50!^0.06 = 7395.788659356498101260513
Показатели = логарифмы.
Взгляните на Логарифм большого десятичного числа