これはちょっとわかりにくいですが、非常に高速に計算でき、aが0から1の間で、bが非常に大きいa^bに似た関数が必要です。多くのbについて、一度に1つのaについて計算されます。理想的には、結果は0.4%以内になります。前もって感謝します。
3 に答える
私のコメントを答えに引き込む:
これb
は整数に丸めるのに十分な大きさであるとおっしゃっているので、1つのアプローチは、 2乗による2乗べき乗アルゴリズムを使用することです。
Math.pow()
非積分パワーを処理する必要があるため、低速です。したがって、整数の累乗アルゴリズムを利用できるため、あなたのケースではより良い結果が得られる可能性があります。
いつものように、実装のベンチマークを行って、実際に。よりも高速かどうかを確認しますMath.pow()
。
OPが検出した実装は次のとおりです。
public static double pow(double a, int b) {
double result = 1;
while(b > 0) {
if (b % 2 != 0) {
result *= a;
b--;
}
a *= a;
b /= 2;
}
return result;
}
これが私の手っ取り早い(最適化されていない)実装です:
public static double intPow(double base,int pow){
int c = Integer.numberOfLeadingZeros(pow);
pow <<= c;
double value = 1;
for (; c < 32; c++){
value *= value;
if (pow < 0)
value *= base;
pow <<= 1;
}
return value;
}
これはすべてのポジティブで機能するはずpow
です。しかし、私はそれに対してベンチマークを行っていませんMath.pow()
。
あなたの特定のケース(「多くのbについて一度に1つのaについて計算される」)については、次のアプローチをお勧めします。
後で特定の計算で使用するテーブルデータを準備します。
可能なbごとに2^Nがbより小さくなるようにNを決定します。
N未満の各nについてテーブルt:t [n] = a ^(2 ^ n)を計算します。これは、t [k + 1] = t [k] *t[k]として効果的に実行されます。
a ^ bを計算します:
- bのバイナリ表現を使用して、a^bをt[i1] t [i2] ... * t [ik]として計算します。ここで、i1..ikはbのバイナリ表現における非ゼロビットの位置です。
アイデアは、異なるbに対してa ^(2 ^ n)の値を再利用することです。
Apache FastMathdouble pow(double d, int e)
は、指数が整数の場合の関数を提供します。
実装はVeltkampのTwoProductアルゴリズムに基づいています。Math.pow
使用法は標準機能と同様です。
import org.apache.commons.math3.util.FastMath;
// ...
FastMath.pow(3.1417, 2);