k
>=整数値である2の最小累乗として計算する必要がありますn
(n
常に> 0です)
現在私は使用しています:
#define log2(x) log(x)/log(2)
#define round(x) (int)(x+0.5)
k = round(pow(2,(ceil(log2(n)))));
これはパフォーマンスが重要な機能にあります
を計算するより計算効率の良い方法はありますk
か?
k
>=整数値である2の最小累乗として計算する必要がありますn
(n
常に> 0です)
現在私は使用しています:
#define log2(x) log(x)/log(2)
#define round(x) (int)(x+0.5)
k = round(pow(2,(ceil(log2(n)))));
これはパフォーマンスが重要な機能にあります
を計算するより計算効率の良い方法はありますk
か?
/* returns greatest power of 2 less than or equal to x, branch-free */
/* Source: Hacker's Delight, First Edition. */
int
flp2(int x)
{
x = x | (x>>1);
x = x | (x>>2);
x = x | (x>>4);
x = x | (x>>8);
x = x | (x>>16);
return x - (x>>1);
}
それを研究し、それがどのように機能するかを見るのは面白いです。どのソリューションが自分の状況に最適であるかを確実に知る唯一の方法は、それらすべてをテキスト フィクスチャで使用してプロファイルし、目的に最も効率的なソリューションを確認することだと思います。
分岐がないため、これは他のいくつかに比べてパフォーマンスの面で非常に優れている可能性がありますが、確認するために直接テストする必要があります.
X 以上の最小の 2 乗が必要な場合は、少し異なるソリューションを使用できます。
unsigned
clp2(unsigned x)
{
x = x -1;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
return x + 1;
}
lim = 123;
n = 1;
while( ( n = n << 1 ) <= lim );
lim よりも大きくなるまで、数値を 2 倍します。
左に 1 シフトすると、値が 2 倍になります。
はい、問題の数値を取得し、ビット シフトを使用して 2 の累乗を決定するだけで、これを計算できます
。 ) 桁。これは、整数除算を 2 で実行するのと同じです。値を左シフトすると、すべてのビットが左に移動し、左端からシフトされたビットが削除され、右端にゼロが追加され、値が実質的に 2 倍になります。数値がゼロになる前に右シフトする必要がある回数を数えると、2 を底とする対数の整数部分が計算されます。次に、それを使用して、値 1 を何回も左シフトして結果を作成します。
int CalculateK(int val)
{
int cnt = 0;
while(val > 0)
{
cnt++;
val = val >> 1;
}
return 1 << cnt;
}
EDIT:代わりに、もう少し簡単に:カウントを計算する必要はありません
int CalculateK(int val)
{
int res = 1;
while(res <= val) res <<= 1;
return res ;
}
int calculate_least_covering_power_of_two(int x)
{
int k = 1;
while( k < x ) k = k << 1;
return k;
}
k = 1 << (int)(ceil(log2(n)));
2 進数は 2 の累乗を表すという事実を利用できます (1 は 1、10 は 2、100 は 4 など)。1 を 2 の指数で左にシフトすると、同じ値が得られますが、はるかに高速です。
ただし、どうにかして ceil(log2(n)) を回避できれば、パフォーマンスが大幅に向上します。
ソース: hackersdelight.org
/* altered to: power of 2 which is greater than an integer value */
unsigned clp2(unsigned x) {
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >>16);
return x + 1;
}
以下を追加する必要があることに注意してください。
x = x | (x >> 32);
64 ビットの数値の場合。