数値の大きさを見つけるための同様の O(1) ビット単位のトリックはありません。多くのマイクロプロセッサ命令セットには、「先頭のゼロをカウントする」ための特別な命令が含まれています。C 言語ファミリには、JavaScript にビット単位の機能を与えるような演算子はありません。
O(1) の唯一の代替手段はMath.floor( Math.log( n ) / Math.LN2 )
、
for ( var i = 0; i == Math.floor( Math.log( 1<<i ) / Math.LN2 ); ++ i ) ;
演算子が 32 ビットの 2 の補数の符号付き算術演算を使用i == 31
しているため、結果として が得られます。<<
純粋主義者になりたい場合は、O( log n
) である 1 だけ繰り返し右シフトするか16 >> i
、i
0 から 4 まで繰り返し右シフトして、結果が 0 の場合はシフトを拒否し、それ以外の場合は を累積し16 >> i
ます。これは O(log log N) です。ここで、N は の最大値でn
あり、一定の時間を意味しますが、すべての確率で よりも遅くなりMath.log
ます。
O( log log N ) アルゴリズムのコード:
var mag = function( n ) {
var acc = 0;
for ( var i = 16; i; i >>= 1 ) {
if ( n >> i ) {
n >>= i;
acc += i;
}
}
return acc;
};
もちろん、これらのいずれについても、インデックスではなく「左端の 1 ビット」を取得するために、結果を 1 つ左にシフトする必要があります。
編集:log
ベースの実装は-Infinity
0 を返しますが、関数mag
は を返しますが0
、これは の結果と同じです1
。最左端の 1 ビットが存在しない可能性を考慮したい場合は、特殊なケースにすることをお勧めします。