web-dev-qa-db-ja.com

「マスクされた」ビットセットの増分

現在、次の問題に遭遇したツリー列挙子を作成中です。

私はマスクされたビットセット、つまりセットビットがマスクのサブセットであるビットセット、つまり0000101マスク付き1010101。私が達成したいのは、ビットセットをインクリメントすることですが、マスクされたビットに関してのみです。この例では、結果は0010000。少し明確にするために、マスクされたビットのみを抽出します。つまり、0011、それらを0100そしてそれらを再びマスクビットに分配し、0010000

ビットスキャンとプレフィックスマスクの組み合わせを使用して手動で操作を実装する以外に、これを行うための効率的な方法を誰かが見ていますか?

78
Tobias Ribizel

キャリーを伝播するために、マスク以外のビットを1で埋めるだけです。

// increments x on bits belonging to mask
x = ((x | ~mask) + 1) & mask;
120
zch

受け入れられた答えと比べて直感的ではありませんが、これはたった3つのステップで機能します。

x = -(x ^ mask) & mask;

これは、zchが示唆するように検証できます。

  -(x ^ mask)
= ~(x ^ mask) + 1  // assuming 2's complement
= (x ^ ~mask) + 1
= (x | ~mask) + 1  // since x and ~mask have disjoint set bits

その後、受け入れられた回答と同等になります。

19
nglee

反復の順序がそれほど重要ではなく、デクリメント操作でニーズが満たされる場合、次の2つの操作のみを使用できます。

始めましょう

_x = mask_

と前の値を取得します

x = (x - 1) & mask

_x - 1_部分は、最後の非ゼロビットをゼロに変更し、下位ビットをすべて1に設定します。次に、_& mask_部分は、マスクビットのみを残します。

7
DAle