Вы сказали, что используете Math.pow()
сейчас и что некоторые вызовы возвращают бесконечное значение.
Если вы можете жить с использованием (гораздо менее точного) doubles
вместо BigDecimals
, то вам следует подумать о том, что математически ,
x = Math.pow(a, x);
эквивалентно
x = Math.pow(a, x - y) * Math.pow(a, y);
Скажем, у вас есть большое значение, давайте назовем его big
, а затем вместо:
// pow(a, big) may return infinite
BigDecimal n = BigDecimal.valueOf(Math.pow(a, big));
Вы можете также сделать:
// do this once, outside the loop
BigDecimal large = BigDecimal.valueOf(a).pow(100);
...
// do this inside the loop
// pow(a, big - 100) should not return infinite
BigDecimal n = BigDecimal.valueOf(Math.pow(a, big - 100)).multiply(large);
Вместо 100 вы можете выбрать другую константу, которая лучше соответствует значениям, которые вы используете. Но что-то вроде вышеприведенного может быть простым решением и намного быстрее, чем вы описываете.
Примечание
Возможно, ApfloatMath.pow()
работает медленно только для больших значений. Если это так, вы можете применить вышеуказанный принцип и к Apfloat.pow()
. Вам нужно будет сделать следующее только один раз, вне цикла :
Apfloat large = ApfloatMath.pow(Constants.BASE_OF_LOG, 100);
и затем вы можете использовать следующие внутри цикла :
x = ApfloatMath.pow(Constants.BASE_OF_LOG, big - 100).multiply(large);
внутри цикла.
Но вам придется проверить, ускоряет ли это процесс. Я мог бы предположить, что ApfloatMath.pow()
может быть намного быстрее для целого показателя степени.
Поскольку я не знаю больше о ваших данных, и поскольку у меня не установлено Apfloat
, я не могу проверить это, поэтому вы должны убедиться, что вышеприведенное решение достаточно для вас ( особенно если он достаточно точен для вас), и если он на самом деле лучше / быстрее, чем у вас.