これは、「集団」機能と呼ばれるビットを数えるための分裂征服戦略の一部です。この戦略の学術的な扱いは、Reingold and Nievergelt、1977に見いだすことができます。
最初にビットをペアごとに合計し、次に4通り、次に8通りなどを合計します。たとえば、ビットが1011
の場合、最初のペア10
は1ビットあり、2番目のビットは10
になるため01
になります。10 = 2
はバイナリで2ビットあり、11
には2ビットあります。 (Beeler氏、GosperとSchroppel、1972を参照)
population(x) = x - (x/2) - (x/4) - (x/8) - (x/16) - ... etc.
あなたが持っている正確なアルゴリズムは「HAKMEM」アルゴリズムとして知られているものの変形である:ここでの基本的な事実があることです。このアルゴリズムは、並列に4ビットフィールドの1
をカウントし、これらの合計は8ビットの合計に変換されます。最後のステップは、0x01010101
を乗算することによって、これらの4バイトを加算する操作です。 0x0F0F0F0F
マスクは、合計でない情報をマスクすることによって、4バイトの合計を取得します。たとえば、8桁のフィールドが10110110
であるとすると、0101
に等しい5ビットがあり、したがって10110101
があります。唯一の最後の4ビットは重要であるので、我々はすなわち、最初の4つをマスク:
10110101 & 0x0F = 00000101
あなたはヘンリー・ウォーレンの著書「ハッカーのディライト」のビットを数えるの特徴点の章全体を見つけることができます。
サイドノート:実際には 'O(1)'ではありません。それは単純なループが 'O(n)'であるのに対して、ビット数に対する 'O(log(n))'です。固定の整数サイズの場合、これと直進ループの両方が 'O(1)'です。 – Mysticial
@Mysticialええ、32ビット整数を考えると、両方ともO(1)です。しかし、これは反復カウントより速いはずですか? – NSF