以下は、整数に設定されたビットの量、つまりそのハミング重みを計算するためにどこかで拾ったアルゴリズムです(正確には、おそらくこの回答から忘れました)。
function hamming_weight($i)
{
$i = $i - (($i >> 1) & 0x55555555);
$i = ($i & 0x33333333) + (($i >> 2) & 0x33333333);
return ((($i + ($i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
(たまたま PHP で便利に使用できましたが、これは実際にはどの言語でも
かまいません。) ひどく間違っていなければ、これは O(1) で実行されます。結局のところ、ブランチはありません。
ここに私が自分で書いたビットカウント関数がありますが、読みやすさは別として、私は劣っていると思います:
function hamming_weight_2($i)
{
$weight = 0;
for ($k = 1, $s = 0; $k < 0xFFFFFFFF; $k *= 2, $s++)
{
$weight += (($i & $k) >> $s);
}
return $weight;
}
しかし、どのような点で劣っているのでしょうか。最初は「ループがあるので、これは線形時間で実行する必要がある」と考えていましたが、ループは入力のサイズにまったく依存しないことに気付きました。$i のサイズに関係なく、反復回数は変わりません。
私が疑問に思っているのはこれです:
- これら 2 つのアルゴリズムは、両方とも O(1) で実行できると本当に言えますか?
- もしそうなら、2つを区別する尺度はありますか? 何らかの形で最初のものの方が優れているはずです。