for (unsigned int i = 1; i <= 100; i++) {
if (i & 0x00000001) {
std::cout << i<<",";
}
}
なぜ (そしてどのように):if( i & 0x00000001 )
奇数を計算しますか?
0x00000001
1
16 進数 (base-16) 表記で書かれていますが、2 進数です。それがその0x
部分です。
&
はビット単位の「AND」演算子で、2 進数 (ビット) 操作に使用されます。
i & 1
最後の 1 を除いて、i のすべての 2 進数をゼロに変換します。
if
ステートメントによる評価のために、結果の 1 ビット数をブール値に変換するのは簡単です。
次のグラフは、i の最後の 16 桁の 2 進数と、それらに何が起こるかを示しています。
i: i in binary: i & 1 in binary: convert to boolean
---- ------------------- ------------------- ---------------------
1 0000000000000001 0000000000000001 true
2 0000000000000010 0000000000000000 false
3 0000000000000011 0000000000000001 true
4 0000000000000100 0000000000000000 false
5 0000000000000101 0000000000000001 true
6 0000000000000110 0000000000000000 false
7 0000000000000111 0000000000000001 true
8 0000000000001000 0000000000000000 false
... ... ... ...
99 0000000001100011 0000000000000001 true
100 0000000001100100 0000000000000000 false
ビットごとの「and」演算子を使用して、最後のビット以外をすべてマスクしています。最後のビットが 1 の場合、その数は奇数です。それは十分な説明ですか?
基数10の数値を見ると、数値が10で割り切れるかどうかを簡単に判断できます。つまり、最後の位置に0があります。上記のコードは、最後の位置の数字も調べますが、基数2です。ゼロ以外の場合、数値は2で割り切れません。
最後のビットをマスクします。数値の2進表現(...、256、128、64、32、16、8、4、2、および1)の各場所を見ると、1つの場所だけが奇数であることがわかります。残りのすべての場所は、ビットが設定されているかクリアされているかに関係なく、偶数の値を持ちます(ゼロは偶数です)。また、偶数を加算すると常に偶数になります。その最後の場所だけが数のパリティを決定します。そのi & &0x00000001
部分は、その最後の場所を分離するだけです。
ビット単位の比較を行っています。bit0とbit0が両方とも1の場合、回答のbit0=1です。
&0x00000001が1であることを確認すると、このビットを持つ数値は奇数です。
0x00000001 = 1
0x00000010 = 2
0x00000011 = 3
etc.
したがって、ビット単位のANDを実行すると
00000001 AND
00000001 =
00000001 (same as true)
00000010 AND
00000001 =
00000000 (same as false)
00000011 AND
00000001 =
00000001 (same as true)
etc
奇数はすべて (2*n+1) の形式の数値で、n は任意の整数 (-2、-1、0、1....) です。したがって、奇数を見つけるには、使用している整数に「+1」が含まれているかどうかを確認する必要があります。符号なし整数として格納されている場合、数値は 2 のべき乗の合計として表すことができます: 2^0 + 2^1 +2^2 + 2^4 など。符号なし整数のバイナリ バージョンは、真理値マップのように見えます。種類: 2 進数に「1」があるすべての場所について、その 2 の累乗を数値に追加します。したがって、符号なし整数のバイナリ表現の右端の桁から開始して左に移動すると、各桁は 2 の累乗を表します。数字が 1 の場合は、その 2 のべき乗を実行中の合計に追加し、2 進数の末尾に到達します。
したがって、10001110b は、2 のべき乗を合計することで整数に変換できます。
右端: 2^1 + 2^2 + 2^3 + 2^7 : 左端 = 141
トリックは、右端の数字が 2^0 を表すことです。これは常に 1 です。他のすべての数字は偶数を表します。したがって、奇数に関しては、「+1」を見つける必要があります。それは右端の桁に対応します。他のすべての数字は、「2*n」形式の数値を表します。したがって、この形式(符号なし整数) の数値が奇数かどうかを判断するには、右端のビットが「1」であるかどうかを確認するだけで済みます。
符号なし整数に対して実行される演算は、論理 AND 演算です。AND'd with 0 はすべて 0 であり、1 AND'd with 1 は 1 です。したがって、演算により、2^0 を表す 2 進数 (1) を除いて、符号なし整数表現のすべての 2 進数が 0 になります。したがって、符号なし整数のバイナリ表現は、奇数の場合は 0x00000001 になり、偶数の場合は 0x00000000 になります。
注: 0x00000000 を書き込むと、「0x」は 16 進数形式であることを意味します。各「0」は 4 ビットを表します。したがって、0x00 は 00000000b の 16 進数です。2 進数で書き出すと、符号なし整数を AND 演算した後の結果として得られる符号なし整数のバイナリ表現は次のようになります。
0000000000000000000000000000000b == 0 および 0000000000000000000000000000001b == 1
次のことを言う前に、私はほとんどの場合、intが奇数か偶数かを判断するためにビットテストを使用していると言います。
しかし、厳密に言えば、を使用する(i % 2)
か、それ((i % 2) != 0)
を判断するのi
は奇妙です。これは、負の数の表現に関係なく機能しますが、1の補数マシン(-3&0x01)では、明らかに奇数であってもゼロ(誤った結果)を返します。
2の補数以外のものを使用して負の数を表す機械は、最近では非常にまれですが、最近のコンパイラーは、(i % 2)
とにかくビットテストに普遍的にコンパイルすることも事実です。そして覚えておいてください、私は通常ここで私自身のアドバイスに従わないので、それはこの提案の真の価値を示しているかもしれません。
たとえば、バイナリを同等にする方法
8 4 2 1
0 0 0 0 = 0
0 0 0 1 = 1
0 0 1 0 = 2
0 0 1 1 = 3
だからあなたはどんな奇妙な番号でも見ることができます。LSBは常に設定されています。チェックするのと同じです:)
私の答えが明確であることを願っています
ビットごとの AND 演算子は、すべてのビットについてこの真理値
表
に
従い
ます
。1,2,4,8,16 ..)、最下位ビットは、値の大小に関係なく、また符号付きか符号なしかに関係なく、唯一の奇数を表します。結果のビットは、両方のオペランドにそのビットが設定されている場合にのみ設定されるため、数値が奇数の場合にのみ結果が真になります。
例: 0b1110101 1 = (1 * 2^0) + (1 * 2^1) + (0 * 2^2) + (1 * 2^3) +
(0 * 2^4) + (1 * 2^ 5) + (1 * 2^6) + (1 * 2^7) = 1 + 2 + 0 + 8 + 0 + 32 + 64 + 128 = 235
最下位ビットが設定されていない場合、値は 234 になり、偶数になります。