この古典的なドキュメントには、整数の下限 (底が 2 の対数) を見つける多くの方法があります。ログを見つけた後、必要な数はもちろん 1 << ログです。
最も魅力的な提案はこれです
// Find the integer log base 2 of an integer with an 64-bit IEEE float
int v; // 32-bit integer to find the log base 2 of
int r; // result of log_2(v) goes here
union { unsigned int u[2]; double d; } t; // temp
t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] = 0x43300000;
t.u[__FLOAT_WORD_ORDER!=LITTLE_ENDIAN] = v;
t.d -= 4503599627370496.0;
r = (t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] >> 20) - 0x3FF;
上記のコードは、指数が 252 に設定されている間、仮数部に整数を格納することにより、64 ビット (IEEE-754 浮動小数点) double に 32 ビット整数 (パディング ビットなし) をロードします。この新しく作成された double から、 252 (double として表される) が減算され、結果の指数が入力値 v の対数底 2 に設定されます。残っているのは、指数ビットを位置 (20 ビット右) にシフトし、バイアス 0x3FF を減算することだけです (これは 10 進数の 1023 です)。この手法は 5 つの操作しか必要としませんが、多くの CPU は double の操作が遅く、アーキテクチャのエンディアンに対応する必要があります。
したがって、必要な最終結果は になります1 << r
。double の操作は、この記事が書かれたときよりもはるかに高速になっていることに注意してください。このコードの最も良い点は、分岐が含まれていないため、うまくパイプライン処理されることです。ぜひ試してみてください。今はベンチマークを試す時間はありませんが、興味深いでしょう。
このコードが C 標準に準拠しているとは保証できません。