はじめに
MQL5には論理演算子とビット単位の論理演算子の2種類があります。
&&や||が論理演算子で、&や|がビット単位の論理演算子となります。
これらは見た目は似ていますが、使用目的や動作が異なります。
&&や||については、下記の記事で詳細を解説しており、MQL5初学者の方はこれを読んでおけば問題はありません。むしろ本記事は読んではいけません(笑)
MQL5 EA講座 第33回「AND条件、OR条件の記述(論理積・論理和)」
その一方で、公式リファレンス内に数多ある有益なサンプルコード内にビット単位の論理演算子である&や|が使われているケースも少なくありません。
従って、一通りの基礎知識がついた状態になったら、MQL5を今後深掘りしていく為にも、ビット単位の論理演算子である&や|の読み解き方や使い方に触れていくのは有用だと思います。
この記事では、&&と&、||と|の違いについて詳しく解説します。
<参照>
・16進数
そもそもビットとは?
ビット(bit) は、コンピュータが情報を扱う最小単位で、0か1のどちらかの値しか取りません。例えるなら、電球のオン(1)とオフ(0)のようなものです。
そもそも2進数とは?
2進数 は、0と1だけを使って数を表現する数の体系です。私たちが普段使っているのは10進数で、0から9までの数字を使いますが、2進数では0と1しか使いません。
ビットは2進数を表現するための単位であり、2進数の各桁が1ビットに対応します。例えば、2進数で「101」と表すと、これは3ビットの情報ということになります。
まとめると、
ビットは2進数の構成要素であり、2進数はビットを使って表現される数である、という関係になります。
以上の前提を踏まえて、この先の記事を読んで頂ければと思います。
論理積(&&)とビット単位の論理積(&)
論理積(&&)
論理積(&&)は、2つの条件が両方とも満たされた場合にのみ、真(true)と判定される演算子です。もしどちらか一方でも偽(false)であれば、結果は偽になります。
- 役割: 両方のオペランド(操作対象の値)が真の場合に真を返します。
- 評価の省略: 左側のオペランド(操作対象の値)が偽の場合、右側のオペランドは評価されません。
- 使用例: 主に条件文で使用されます。
bool a = true, b = false;
if (a && b) { // bは評価されない
// ...
}
このコードは、変数aとbが両方とも真(true)の場合にのみ特定の処理を実行する条件文の例です。
変数aは真ですが、変数bは偽(false)なので、条件を満たさず、特定の処理は実行されません。
この場合、変数aが偽と判断された時点で、変数bの真偽は確認されずに処理が終了します。
ビット単位の論理積(&)
ビット単位の論理積は、2つの数値を2進数で表現し、各桁のビットに対して論理積を計算する演算子です。それぞれの桁において、両方のビットが1の場合のみ、結果のビットも1になります。
- 役割: 各ビットに対して、両方のビットが1の場合に1を、それ以外の場合に0を返します。
- 評価の省略なし: 両方のオペランド(操作対象の値)が必ず評価されます。
- 使用例: 主にフラグの操作などで使用されます。
int x = 5, y = 3; // 2進数で x = 101, y = 011
int z = x & y; // z = 1 (2進数で 001)
詳細解説
2進数の仕組み
2進数は、0と1の2種類の数字で構成される数値表現方法です。各桁が2の累乗(同じ数を複数回かけ合わせること)の値を持ちます。例えば、5を2進数で表すと101になります。
※5を2進数で表すには、5を2で割っていくことを繰り返します。
- 5 ÷ 2 = 2 あまり 1
- 2 ÷ 2 = 1 あまり 0
- 1 ÷ 2 = 0 あまり 1
ここで、割り切れなくなるまで計算したら、最後に出てきたあまりを下から順に並べます。
つまり、101が5の2進数での表現になります。
データとメモリの仕組み
コンピュータは、メモリ内でデータをビットの配列として扱います。各ビットは電圧の高低に対応し、0または1の状態を取ります。メモリ内のデータは、これらのビットが連続して並んだものです。
ビット単位の論理積(&)の仕組み
ビット単位の論理積(&)は、対応するビットが両方とも1の場合に1を、それ以外の場合に0を返す演算です。
実例:x & yの解説
最初のコード例を改めて見てみましょう。
int x = 5, y = 3; // 10進数で x = 5, y = 3
int z = x & y; // ビット単位の論理積を計算して z に代入
10進数から2進数への変換
5を2進数で表すには、5を2で何回割れるか考えます。
- 5は2で2回割れて、1あまります。(5 ÷ 2 = 2 あまり 1)
- 2は2で1回割れて、0あまります。(2 ÷ 2 = 1 あまり 0)
- 1は2で割れないので、そのまま1です。
このあまりを逆に並べると、101になります。これが5の2進数です。
3を2進数で表すには、3を2で何回割れるか考えます。
- 3は2で1回割れて、1あまります。(3 ÷ 2 = 1 あまり 1)
- 1は2で割れないので、そのまま1です。
このあまりを逆に並べると、11になります。
2進数は、0と1だけで数を表すので、3桁で表すために、一番左に0を加えて、011となります。これが3の2進数です。
ビット単位の論理積の計算
101 (x)
& 011 (y)
-------
001 (z)
各ビットの説明
このように、x (101) と y (011) で、1が両方とも立っているのは一番下の桁だけなので、z は 001 となります。
これにより、zは001(2進数)になります。10進数で表すと、001(2進数)は1(10進数)です。
int z = 1; // 10進数での結果
論理和(||)とビット単位の論理和(|)
論理和(||)
論理和(||)は、2つの条件のうち、少なくとも1つが満たされた場合に真(true)と判定される演算子です。どちらか一方でも真であれば、結果は真になります。
- 役割: どちらかのオペランド(操作対象の値)が真の場合に真を返します。
- 評価の省略: 左側のオペランド(操作対象の値)が真の場合、右側のオペランドは評価されません。
- 使用例: 主に条件文で使用されます。
bool a = true, b = false;
if (a || b) { // bは評価されない
// ...
}
このコードは、変数a
または b
の少なくとも一方が真 (true) の場合に特定の処理を実行する条件文の例です。
変数a
は真なので、条件を満たし、特定の処理が実行されます。
この場合、変数a
が真と判断された時点で、変数b
の真偽は確認されずに処理が終了します。
ビット単位の論理和(|)
ビット単位の論理和(|)は、2つの数値を2進数で表現し、各桁のビットに対して論理和を計算する演算子です。それぞれの桁において、どちらか一方のビットが1であれば、結果のビットも1になります。
- 役割: 各ビットに対して、どちらかのビットが1の場合に1を、それ以外の場合に0を返します。
- 評価の省略なし: 両方のオペランド(操作対象の値)が必ず評価されます。
- 使用例: 主にフラグの操作などで使用されます。
int x = 5, y = 3; // 2進数で x = 101, y = 011
int z = x | y; // z = 7 (2進数で 111)
詳細解説
実例:x | yの解説
コード例を改めて見てみましょう。
int x = 5, y = 3; // 10進数で x = 5, y = 3
int z = x | y; // ビット単位の論理和を計算して z に代入
10進数から2進数への変換
x=5
5を2進数で表すには、5を2で何回割れるか考えます。
- 5は2で2回割れて、1あまります。(5 ÷ 2 = 2 あまり 1)
- 2は2で1回割れて、0あまります。(2 ÷ 2 = 1 あまり 0)
- 1は2で割れないので、そのまま1です。
このあまりを逆に並べると、101になります
y=3
3を2進数で表すには、3を2で何回割れるか考えます。
- 3は2で1回割れて、1あまります。(3 ÷ 2 = 1 あまり 1)
- 1は2で割れないので、そのまま1です。
このあまりを逆に並べると、11になります。
2進数は、0と1だけで数を表すので、3桁で表すために、一番左に0を加えて、011となります
ビット単位の論理和の計算
101 (x)
| 011 (y)
-------
111 (z)
各ビットの説明
|
(ビット単位の論理和) は、各桁のビットのどちらか一方でも1であれば、結果のビットも1になる演算です。
x (101) と y (011) で、各桁のどちらかに1が必ずあるので、z は 111 となります。
int z = 7; // 10進数での結果
まとめ
演算子 | 説明 | 評価の省略 | 主な用途 |
---|---|---|---|
&& | 論理積 | あり | 条件文 |
& | ビット単位の論理積 | なし | フラグ操作 |
|| | 論理和 | なし | 論理和 |
| | ビット単位の論理和 | なし | フラグ操作 |
論理演算子(&&, ||)は、主に条件文で複数の条件を組み合わせる際に使用します。一方、ビット単位の論理演算子(&, |)は、主に数値のビット単位の操作を行う際に使用します。それぞれの特徴を理解し、適切に使い分けることが重要です。