Python Language
ビット演算子
サーチ…
前書き
ビット単位の操作は、ビットレベルでバイナリ文字列を変更します。これらの操作は非常に基本的であり、プロセッサーによって直接サポートされています。これらの操作は、デバイスドライバ、低レベルのグラフィックス、暗号化、およびネットワーク通信の操作に必要です。この節では、Pythonのビット演算子に関する有益な知識と例を提供します。
構文
x << y#ビット単位の左シフト
x >> y#ビット単位の右シフト
x&y#ビット単位のAND
x | y#ビットOR
〜x#Bitwise NOT
x ^ y#ビット単位のXOR
ビット単位AND
&
演算子はバイナリANDを実行し、 両方のオペランドにビットが存在する場合、そのビットがコピーされます。つまり、
# 0 & 0 = 0
# 0 & 1 = 0
# 1 & 0 = 0
# 1 & 1 = 1
# 60 = 0b111100
# 30 = 0b011110
60 & 30
# Out: 28
# 28 = 0b11100
bin(60 & 30)
# Out: 0b11100
ビット単位OR
|
演算子はバイナリ "or"を実行します。この場合、どちらのオペランドにもビットがコピーされます。つまり、
# 0 | 0 = 0
# 0 | 1 = 1
# 1 | 0 = 1
# 1 | 1 = 1
# 60 = 0b111100
# 30 = 0b011110
60 | 30
# Out: 62
# 62 = 0b111110
bin(60 | 30)
# Out: 0b111110
ビット単位の排他的論理和(排他的論理和)
^
演算子は、バイナリ1
がコピーされるバイナリXORを実行します。バイナリ1
は、それがちょうど1つのオペランドの値である場合にのみコピーされます。これを示す別の方法は、オペランドが異なる場合にのみ結果が1
なることです。例としては、
# 0 ^ 0 = 0
# 0 ^ 1 = 1
# 1 ^ 0 = 1
# 1 ^ 1 = 0
# 60 = 0b111100
# 30 = 0b011110
60 ^ 30
# Out: 34
# 34 = 0b100010
bin(60 ^ 30)
# Out: 0b100010
ビット単位の左シフト
<<
演算子は、左のオペランドの値が右のオペランドによって与えられたビット数だけ左に移動するビット単位の「左シフト」を実行します。
# 2 = 0b10
2 << 2
# Out: 8
# 8 = 0b1000
bin(2 << 2)
# Out: 0b1000
1
左ビットシフトを実行することは、 2
を乗算することと等価である。
7 << 1
# Out: 14
n
左ビットシフトを実行することは、 2**n
による乗算と等価である。
3 << 4
# Out: 48
ビット単位の右シフト
>>
演算子は、ビットごとの "右シフト"を実行します。ここで、左のオペランドの値は、右のオペランドによって与えられたビット数だけ右に移動します。
# 8 = 0b1000
8 >> 2
# Out: 2
# 2 = 0b10
bin(8 >> 2)
# Out: 0b10
1
右ビットシフトを実行することは、 2
による整数除算に相当します。
36 >> 1
# Out: 18
15 >> 1
# Out: 7
n
右ビットシフトを実行することは、整数除算を2**n
と等価にします。
48 >> 4
# Out: 3
59 >> 3
# Out: 7
ビット単位NOT
~
演算子は、数値のすべてのビットを反転します。コンピュータは符号付き数値表現を使用しているため、負の2進数を符号化する2の補数表記を使用します。この場合、負の数値は先行ゼロ(0)ではなく先頭の1になります。
これは、8ビットを使用して2の補数を表す場合、 0000 0000
から0111 1111
までのパターンを0から127までの数字を表すように扱い、 1xxx xxxx
は負の数を表すように予約することを意味します。
8ビットの2の補数
ビット | 符号なし値 | 2の補数の値 |
---|---|---|
0000 0000 | 0 | 0 |
0000 0001 | 1 | 1 |
0000 0010 | 2 | 2 |
0111 1110 | 126 | 126 |
0111 1111 | 127 | 127 |
1000 0000 | 128 | -128 |
1000 0001 | 129 | -127 |
1000 0010 | 130 | -126 |
1111 1110 | 254 | -2 |
1111 1111 | 255 | -1 |
これは、本質的に、 1010 0110
が(128 * 1) + (64 * 0) + (32 * 1) + (16 * 0) + (8 * 0) + (4 * 1) + (2 * 1) + (1 * 0)
(128 * 1) - (64 * 0) - (32 * 1) - (16 * 0) - (8 * 0) - (4 * 1) - (2 * 1) - (1 * 0)
(128 * 1) + (64 * 0) + (32 * 1) + (16 * 0) + (8 * 0) + (4 * 1) + (2 * 1) + (1 * 0)
)の2の補数の値を持つ(128 * 1) - (64 * 0) - (32 * 1) - (16 * 0) - (8 * 0) - (4 * 1) - (2 * 1) - (1 * 0)
このようにして、負の数は-128( 1000 0000
)になります。ゼロ(0)は0000 0000
、マイナス1(-1)は1111 1111
と表されます。
しかし一般的に、これは~n = -n - 1
意味します。
# 0 = 0b0000 0000
~0
# Out: -1
# -1 = 0b1111 1111
# 1 = 0b0000 0001
~1
# Out: -2
# -2 = 1111 1110
# 2 = 0b0000 0010
~2
# Out: -3
# -3 = 0b1111 1101
# 123 = 0b0111 1011
~123
# Out: -124
# -124 = 0b1000 0100
要約することができ、正の数に適用されたときに、この操作の全体的な影響に注意してください 。
~n -> -|n+1|
そして、負の数に適用すると、対応する効果は次のようになります。
~-n -> |n-1|
次の例はこの最後のルールを示しています...
# -0 = 0b0000 0000
~-0
# Out: -1
# -1 = 0b1111 1111
# 0 is the obvious exception to this rule, as -0 == 0 always
# -1 = 0b1000 0001
~-1
# Out: 0
# 0 = 0b0000 0000
# -2 = 0b1111 1110
~-2
# Out: 1
# 1 = 0b0000 0001
# -123 = 0b1111 1011
~-123
# Out: 122
# 122 = 0b0111 1010
埋め込み操作
すべてのビット演算子( ~
を除く)は独自のインプレースバージョンを持っています
a = 0b001
a &= 0b010
# a = 0b000
a = 0b001
a |= 0b010
# a = 0b011
a = 0b001
a <<= 2
# a = 0b100
a = 0b100
a >>= 2
# a = 0b001
a = 0b101
a ^= 0b011
# a = 0b110