salice の答えを少し拡張します。
ビットテスト
テスト パターンを作成できるので、各ビットを個別にチェックする必要はありません (整数をテストする方が、1 ビットずつテストするよりも高速です。良い):
testOnes = 128 & 64 // the bits we want to be 1
testZeros = ~(8 & 4) // the bits we want to be 0, inverted
次に、この方法でテストを実行します。
if (!(~(x & testOnes) & testOnes) &&
!(~(~x | testZeros))) {
/* match! */
}
ロジックの説明:
まず第一に、両方testOnes
で、testZeros
関心のあるビットを 1 に設定し、残りを 0 に設定します。
testOnes testZeros
11000000 11110011
次にx & testOnes
、1 であるかどうかをテストしたくないすべてのビットをゼロにします ( と の違いに注意してください&
:&&
は&
論理AND
演算をビット単位で実行しますが、 は整数の論理演算です) &&
。AND
testOnes
11000000
x x & testOnes
11110000 11000000
11000010 11000000
01010100 01000000
現在、1 であるかどうかをテストしているビットはせいぜい 1 である可能性がありますが、それらすべてが 1 であるかどうかはわかりません。結果 ( ~(x & testOnes)
) を反転すると、1 であることを気にしないすべての数値とテストしたいのは、0 (1 の場合) または 1 (0 の場合) です。
testOnes
11000000
x ~(x & testOnes)
11110000 00111111
11000010 00111111
01010100 10111111
AND
それをビット単位で処理することによりtestOnes
、関心のあるビットがすべて 1 の場合は 0 になりx
、それ以外の場合は非ゼロになります。
testOnes
11000000
x ~(x & testOnes) & testOnes
11110000 00000000
11000010 00000000
01010100 10000000
この時点で、1 をテストしたいすべてのビットが実際に 1 の場合は 0 であり、それ以外の場合は非 0 であるため、論理演算を実行しNOT
て 0 をtrue
に、非 0 を に変換しfalse
ます。
x !(~(x & testOnes) & testOnes)
11110000 true
11000010 true
01010100 false
ゼロビットのテストも同様ですが、bitwise- ( ) の代わりに bitwise- ( ) を使用する必要OR
が|
ありAND
ます&
。まず、 を反転x
して、0 であるべきビットOR
を 1 にする必要があります。したがって、この時点で、0 であるべきビットx
が実際に 0 の場合はすべて 1 であり、そうでない場合はすべて 1 ではないため、結果を再度反転して、最初のケースで 0 を取得し、2 番目のケースで非 0 を取得します。 . 次に、論理NOT
( ) を適用して、結果を(最初のケース) または(2 番目のケース)!
に変換します。true
false
testZeros
11110011
x ~x ~x | testZeros ~(~x | testZeros) !(~(~x | testZeros))
11110000 00001111 11111111 00000000 true
11000010 00111101 11111111 00000000 true
01010100 10101011 11111011 00000100 false
注: 各テストで 4 つの操作を実行したため、合計で 8 つの操作を実行したことを認識する必要があります。テストするビット数によっては、これでも各ビットを個別にチェックするよりも少ない場合があります。
算術テスト
等しいかどうかのテストは簡単です:XOR
テストされた数値 -- すべてのビットが等しい (したがって数値が等しい) 場合は 0 を取得し、少なくとも 1 つのビットが異なる (したがって数値が異なる) 場合は 0 以外を取得します。(適用するNOT
と、同等のテスト結果true
が 、差が になりfalse
ます。)
ただし、不等式をテストするには、少なくとも論理演算に適用される場合、ほとんどの場合運が悪くなります。2 の累乗 (例: 質問の 16) のチェックは論理演算 (ビットごとAND
の 0 のテスト) で行うことができますが、2 の累乗ではない数値の場合、そうではありません。簡単。例として、 をテストしてみましょうx>5
: パターンは 00000101 ですが、どのようにテストしますか? 最初の 5 つの最上位ビットに 1 がある場合、数値は大きくなりますが、最初の 5 ビットがすべて 0 である 6 (00000110) も大きくなります。
あなたができる最善のことは、数値が数値の最大の 2 の累乗の少なくとも 2 倍であるかどうかをテストすることです (上記の例では 5 に対して 4)。はいの場合、元のサイズよりも大きくなっています。それ以外の場合は、少なくとも 2 の累乗の最大値と同じである必要があり、下位ビットに対して同じテストを実行します。ご覧のとおり、操作の数は、テスト番号の 1 ビットの数に基づいて動的です。
リンクされたビット
これがあなたXOR
の友達です。2 つのビットXOR
が同じ場合は 0 になり、そうでない場合は 1 になります。
テストを実行する簡単な方法はわかりませんが、次のアルゴリズムが役立つはずです。
b1
ビット, ...を同じ (すべて 1 またはすべて 0) にする必要があると仮定bn
し、他のすべてのビットをゼロにして (AND
上記の論理を参照)、テスト パターン内の各ビットを分離し、それらを次の位置に並べます。同じ位置 (便宜上、最下位ビットにしましょう)。次にXOR
、それらのうちの 2 つをXOR
-ing し、結果を 3 つ目に -ing すると、奇数ステップごとに偶数が生成され、元の数でビットが同じである場合は、偶数ステップごとに奇数が生成されます。最終結果のみをテストすると、テスト対象のリンクされたビットが多数になると正しくない可能性があるため、すべてのステップでテストする必要があります。
testLinks
00110000
x x & testLinks
11110000 00110000
11000010 00000000
01010100 00010000
x x's bits isolated isolated bits shifted
11110000 00100000 00000001
00010000 00000001
11000010 00000000 00000000
00000000 00000000
01010100 00000000 00000000
00010000 00000001
x x's bits XOR'd result
11110000 00000000 true (1st round, even result)
11000010 00000000 true (1st round, even result)
01010100 00000001 false (1st round, odd result)
注: C ライクな言語では、XOR
演算子は^
.
注: ビットを同じ位置に並べるには? ビットシフト。左シフト ( <<
) は、すべてのビットを左にシフトし、最上位ビットを「失い」、最下位ビットに 0 を「導入」し、基本的に数値を 2 倍します。shift-right ( >>
) も同様に動作し、ビットを右にシフトし、基本的に整数を 2 で除算しますが、同じビットを既に存在していた最上位ビットに「導入」します (したがって、負の数を負のままにします)。 .