ApfloatMath.pow отнимает много времени - PullRequest
0 голосов
/ 28 апреля 2018

Я должен найти журнал, а затем после нескольких вычислений антилог многих больших десятичных чисел. Поскольку log и antilog не поддерживаются для чисел BigDecimal, для этого я использовал библиотеку Apfloat и использовал ее метод pow, который может принимать оба аргумента в качестве значений Apfloat, как показано ниже:

ApfloatMath.pow (Constants.BASE_OF_LOG, apFloatNum);

Проблема в том, что я использую его в цикле, а цикл большой. Apfloat Pow занимает много времени, чтобы найти мощность, которая составляет более часа. Чтобы избежать этого, я подумал о том, чтобы преобразовать Apfloat в double и затем использовать Math.pow, который работает быстро, но дает мне бесконечность для нескольких значений.

Что мне делать? Кто-нибудь знает альтернативу ApfloatMath.pow?

1 Ответ

0 голосов
/ 28 апреля 2018

Вы сказали, что используете 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, я не могу проверить это, поэтому вы должны убедиться, что вышеприведенное решение достаточно для вас ( особенно если он достаточно точен для вас), и если он на самом деле лучше / быстрее, чем у вас.

...