ビット演算は、昔はメモリ領域の節約のために用いられる手法でしたが、最近ではメモリも潤沢にあるので、使う機会も減りました。
ですが、使いどころによっては様々な状態を表す演算として有用となりますので、いつでも使えるようにしておくことが望ましい機能です。
本記事では、Goにおけるビット演算について解説します。
記事内に記載しているプログラムは、Go1.15.2を使って動作確認をしています。
Goのビット演算
Goのビット演算について、以下の内容を解説します。
- Goでのビット演算の扱い方
- AND演算
- OR演算
- XOR演算
- AND NOT演算
- 左シフト演算
- 右シフト演算
Goでのビット演算の扱い方
ビット演算はその名の通り、1ビット単位で演算を行うので、プログラムも2進数で表現していきます。
Goで2進数で表現するには、先頭に 0b をつけます。
bit := 0b1010 fmt.Println(bit) // -> 10
2進数のまま表示するには、Printf文の%bを使います。
fmt.Printf("%08b\n", bit) // -> 00001010
上記のプログラムでは、8桁の左0埋めで2進数表記するように指定しています。
AND演算
AND演算を行うには、演算子&を使います。
AND演算は演算するビット同士が1であれば結果は1、それ以外の組み合わせは0となる計算を行います。
a := 0b1010 b := 0b0110 r := a & b fmt.Printf("%08b\n", r) // -> 00000010 fmt.Println(r) // -> 2
上記のプログラムは、「0b1010」と「0b0110」のAND演算になるので、結果は「0b0010」となって2となります。
OR演算
OR演算を行うには、演算子|を使います。
OR演算は演算するどちらかのビット1であれば結果は1、両方のビットが0であれば結果は0となる計算を行います。
a = 0b1010 b = 0b0110 r = a | b fmt.Printf("%08b\n", r) // -> 00001110 fmt.Println(r) // -> 14
上記のプログラムは、「0b1010」と「0b0110」のOR演算になるので、結果は「0b1110」となって14となります。
XOR演算
XOR演算を行うには、演算子^を使います。
XOR演算は演算するビットが0と1で異なる場合は結果は1、ビットが同じ0同士または1同士であれば結果は0となる計算を行います。
a = 0b1010 b = 0b0110 r = a ^ b fmt.Printf("%08b\n", r) // -> 00001100 fmt.Println(r) // -> 12
上記のプログラムは、「0b1010」と「0b0110」のXOR演算になるので、結果は「0b1100」となって12となります。
AND NOT演算
GoではNOT演算はありませんが、AND NOT演算ができます。演算子 &^ を使います。
演算の2つ目(下記ではb)のNOT演算を行った後に、1つ目(下記ではa)とAND演算を行います。
a = 0b1010 b = 0b0110 r = a &^ b fmt.Printf("%08b\n", r) // -> 00001000 fmt.Println(r) // -> 8
上記のプログラムは、2つ目の「0b0110」の否定が「0b1001」となって、1つ目の「0b1010」とのAND演算を行って、結果は「0b1000」となって8となります。
左シフト演算
左シフト演算は、演算子<<を使って、ビットをそのまま指定した数だけ左に移動させます。
左端はそのまま桁あふれとなり、右端から0が入ってきます。
a = 0b1010 r = a << 2 fmt.Printf("%08b\n", r) // -> 00101000 fmt.Println(r) // -> 40
上記のプログラムは、「0b1010」を2桁左に移動して、「0b101000」となって40となります。
左シフトするごとに2倍になっていくことになります。
右シフト演算
右シフト演算は、演算子>>を使って、ビットをそのまま指定した数だけ右に移動させます。
右端は切り捨てられ、左端は正の数であれば0、負の数であれば1が入って、符号をそのまま引継ぎます。
a = 0b1010 r = a >> 2 fmt.Printf("%08b\n", r) fmt.Println(r)
上記のプログラムは、「0b1010」を2桁左に移動して、「0b0010」となって2となります。
右シフトするごとに1/2になっていくことになります。
ただし、端数は切り捨てで1より小さくなることはありません。
まとめ
Goのビット演算についてまとめると、以下となります。
- Goで2進数を扱うには、値の先頭に0bを付ける。
- ビット演算は各ビットに対して演算を行う。
- シフト演算は各ビットを移動させて演算を行う。
通常あまり使う機会はないかもしれませんが、桁に意味を持たせてフラグ管理したい場合などに使ってみてはいかがでしょうか。
今回は、Goのビット演算について解説しました。
以上、参考になれば幸いです。
コメント