指数関数の出力が入力値を超えるまでプログラムを実行し続け、それを指数関数の前の出力と比較する必要があります。たとえ疑似コードであっても、どうすればそのようなことをすることができますか?
9 に答える
- 与えられた数値から 2 を底とする対数を求める => x := log (2, 入力)
- 1で取得した値を上下に丸める => y := round(x), z := round(x) + 1
- 2^y, 2^z を見つけて、両方を入力と比較し、より適した方を選択します
ループとは別に、コンパイラが nlz 命令をどのようにマップするかによって、より高速になる可能性がある 1 つの解決策もあります。
public int nextPowerOfTwo(int val) {
return 1 << (32 - Integer.numberOfLeadingZeros(val - 1));
}
明示的なループはなく、 を使用したソリューションよりも確実に効率的ですMath.pow
。コンパイラがnumberOfLeadingZeros
.
これにより、2 の低いべき乗を簡単に取得し、どちらが近いかを比較できます。最後の部分は、私には思われる各ソリューションに対して実行する必要があります。
使用している言語に応じて、ビット単位の操作を使用してこれを簡単に行うことができます。入力値に設定された最上位 1 ビットよりも大きい単一の 1 ビットが設定された値、または入力値に設定された最上位 1 ビットが設定された値のいずれかが必要です。
最上位の設定ビットより下のすべてのビットを 1 に設定する場合は、1 を追加すると、2 の次の累乗になります。これを右にシフトして、次に低い 2 の累乗を取得し、2 つの近い方を選択できます。
unsigned closest_power_of_two(unsigned value)
{
unsigned above = (value - 1); // handle case where input is a power of two
above |= above >> 1; // set all of the bits below the highest bit
above |= above >> 2;
above |= above >> 4;
above |= above >> 8;
above |= above >> 16;
++above; // add one, carrying all the way through
// leaving only one bit set.
unsigned below = above >> 1; // find the next lower power of two.
return (above - value) < (value - below) ? above : below;
}
他の同様のトリックについては、 Bit Twiddling Hacksを参照してください。
x を 1 に設定します。
x < ターゲットの間、x = 2 * x に設定
次に、x または x / 2 のうち、ターゲットに近い方を返します。
これはビット単位の解決策です。同数の場合は 2^N と 2^(N+1) の小さい方を返します。これは、log() 関数の呼び出しに比べて非常に高速です。
let mask = (~0 >> 1) + 1
while ( mask > value )
mask >> 1
return ( mask & value == 0 ) ? mask : mask << 1
public static int neareastPower2(int in) {
return (int) Math.pow(2, Math.round(Math.log(in) / Math.log(2)));
}
入力数値を受け取って答えを返す関数の疑似コードを次に示します。
int findit( int x) {
int a = int(log(x)/log(2));
if(x >= 2^a + 2^(a-1))
return 2^(a+1)
else
return 2^a
}
public static int neareastPower2(int in) {
if (in <= 1) {
return 1;
}
int result = 2;
while (in > 3) {
in = in >> 1;
result = result << 1;
}
if (in == 3) {
return result << 1;
} else {
return result;
}
}
簡単な例として、50 の代わりに 5 を入力として使用します。
- 入力をビット/バイトに変換します。この場合は 101
- 2 のべき乗を探しているので、答えはすべて 10000...00 (一定量のゼロを含むもの) の形式になります。入力値 (3 ビット) を取得し、100 (3 ビット) と 1000 (4 ビット) の整数値を計算します。整数 100 は入力よりも小さくなり、整数 1000 は大きくなります。
- 入力と 2 つの可能な値の差を計算し、最小のものを使用します。この場合、100 = 4 (1 の差) であり、1000 = 8 (3 の差) であるため、検索される答えは 4 です。