リストHOME  リストOpen Source

第9回VBAプログラム豆知識

概要 ~ ビット演算その1 ~

 第9回は、VBAで、論理演算子を使ったビット演算について、解説したいと思います。 ビット演算は、2進数で考えなければいけませんので、馴染みのない方は、難しい印象を受けるかもしれませんが、実は非常に単純な理論ですので、そのあたりを今回、解説できればと思います。ビットの演算に先立って、VBAで利用できる論理演算子と、その演算の真理値表を紹介します。

論理演算子の真理値表


 このようにVBAで利用できる論理演算子には、And、Or、Xor、Eqv、Imp、Notがあります。よくプログラムで使用するのは、And、Or、Xor、Not、あたりでしょうか。私の経験上、Eqv、Impについては、ほとんど使用する機会はないように思います。今回は、And、Or、Notの演算子に絞り、例を用いて説明していきます。

サンプルファイルのダウンロード


And、Or、Not演算

 And演算、Or演算及び、Not演算について、数値を使って説明したいと思います。
まず、論理積(And)についてですが、簡単な例を示すと以下のようになります。

論理積And


 これは、100(10進数)170(10進数)論理積(And)を求めたもので、その時の値は32(10進数)となります。


 この例を、実際にプログラムで実装したものが以下となり、サンプルファイルの【論理積(And)】ボタンを押下することで、実行できます。


'論理積(And演算)
Private Sub CBtnAnd_Click()
    Dim A As Byte
    Dim B As Byte
    Dim C As Byte
    
    A = 100
    B = 170
    C = A And B
    
    Debug.Print "A = " & A & vbTab & "(2進:" & BIN_STR(A) & ")"
    Debug.Print "B = " & B & vbTab & "(2進:" & BIN_STR(B) & ")"
    Debug.Print "C = " & C & vbTab & "(2進:" & BIN_STR(C) & ")"
    
End Sub


 実際に、【論理積(And)】ボタンを押した時の、出力結果が以下です。
上の真理値表での演算結果 32(2進:00100000) と一致することが確認できます。



A = 100 (2進:01100100)
B = 170 (2進:10101010)
C = 32  (2進:00100000)


 次に、論理和(Or)の例ですが、以下のようになります。

論理和Or


 この論理和の例を、プログラムで実装したものが以下で、これは、サンプルファイルの【論理和(Or)】ボタンを押下することで、実行できます。



'論理積(Or演算)
Private Sub CBtnOr_Click()
    Dim A As Byte
    Dim B As Byte
    Dim C As Byte
    
    A = 100
    B = 170
    C = A Or B
    
    Debug.Print "A = " & A & vbTab & "(2進:" & BIN_STR(A) & ")"
    Debug.Print "B = " & B & vbTab & "(2進:" & BIN_STR(B) & ")"
    Debug.Print "C = " & C & vbTab & "(2進:" & BIN_STR(C) & ")"

End Sub


【論理和(Or)】ボタンを押した時の、出力結果が以下です。
上の真理値表での演算結果 238(2進:11101110) と一致することが確認できます。



A = 100 (2進:01100100)
B = 170 (2進:10101010)
C = 238 (2進:11101110)


 続いて、論理否定演算Notを、例を用いて説明したいと思います。

論理否定Not


 これは、170(2進:10101010)論理否定(Not)を求めたもので、その時の値は85(2進:01010101)となります。


 この例を、実際にプログラムで実装したものが以下となり、サンプルファイルの【論理否定(Not)】ボタンを押下することで、実行できます。


'論理否定(Not演算)
Private Sub CBtnNot_Click()
    Dim A As Byte
    Dim B As Byte
    
    A = 170
    B = Not A
    
    Debug.Print "A = " & A & vbTab & "(2進:" & BIN_STR(A) & ")"
    Debug.Print "B = " & B & vbTab & "(2進:" & BIN_STR(B) & ")"
    
End Sub


 実際に、【論理否定(Not)】ボタンを押した時の、出力結果が以下です。
上の真理値表を使った演算結果 85(2進:01010101) と一致することが確認できます。



A = 170 (2進:10101010)
B = 85  (2進:01010101)


 上記で、論理積(And)、論理和(Or)、論理否定(Not)の演算について簡単に説明しましたが、次は、プログラムにおける、これらの論理演算の具体的な使い方を説明したいと思います。


ビットを立てる/落とす

 プログラムで、意図したビットを立てた(0→1)データを作成するときは、論理和(Or)を使用します。
その際に、以下の早見表があると便利ですので、参考にしてください。これは、あるビットを立てた場合の、16進値を探すときに使用します。立てるビット桁を大きくしていくと、16進値は、1、2、4、8を繰り返しながら、桁が増えていきます

<16進値早見表>
各ビットを立てたときの16進値早見表


 例えば、1ビット目、3ビット目、5ビット目を立てたデータを作るとします。各ビットの値を立てた時の、16進値を早見表で確認すると、それぞれ、&H01、&H04、&H10となっています。この値をすべて、Or演算子で連結すると、1、3、5ビット目が立った値が作成できます。



値 = &H01 Or &H04 Or &H10

 この値を真理値表に基づいて計算すると、以下のように値21(2進:00010101)となります。

ビットを立てたときの真理値表


 これを、プログラムで実装すると以下となり、このプログラムは、サンプルファイルの【1、3、5ビット目を立てる】ボタンを押すことで実行可能です。



'1、3、5ビット目を立てます。
Private Sub CBtnBits_Click()
    Dim A As Byte
    
    A = &H1 Or &H4 Or &H10

    Debug.Print "A = " & A & vbTab & "(2進:" & BIN_STR(A) & ")"

End Sub


 実行結果は以下となり、先に、真理値表を基にして算出した値21と合致することが分かります。



A = 21  (2進:00010101)


 逆に、あるデータの特定のビットを落としたい場合は、And演算子とNot演算子を使用します。手順としては、まず、落としたいビットを組み合わせた論理和値を算出し、その値Not演算子で反転させます。次に、この値と、ビットを落としたい値との論理積(And)を取ります。これにより、落としたい値の、対象ビットが0となるはずです。


 それでは、先ほど作成したデータ21(2進:00010101)の、1、3ビット目のデータを落としてみましょう。

ビットを落としたときの真理値表



値 = 21 And Not(&H01 Or &H04)



 これを、プログラムで実装すると以下となり、このプログラムは、サンプルファイルの【1、3、5ビット目を落とす】ボタンを押すことで実行可能です。



'1、3ビット目を落とします。
Private Sub CBtnBitsOff_Click()
    Dim A As Byte
    Dim B As Byte
    Dim C As Byte
    
    A = 21
    B = &H1 Or &H4
    B = Not B
    C = A And B

    Debug.Print "A = " & A & vbTab & "(2進:" & BIN_STR(A) & ")"
    Debug.Print "B = " & B & vbTab & "(2進:" & BIN_STR(B) & ")"
    Debug.Print "C = " & C & vbTab & "(2進:" & BIN_STR(C) & ")"

End Sub


 実行結果は以下となり、先に、真理値表を基にして算出した値16と合致することが確認できました。



A = 21  (2進:00010101)
B = 250 (2進:11111010)
C = 16  (2進:00010000)

ビットのチェック

 プログラムであるデータの特定のビットが、立っているかどうかをチェックするには、論理演算子の論理積(And)を使用します。例えば、8ビット目が立っているかどうかをチェックするには、&H80(早見表の8ビット目)と論理積(And)を取ります。この時に演算結果が、0(False)でなければ、8ビット目が立っているということになります。

ビットのチェック(単一)


 このことを確認するためのプログラムが以下となります。サンプルファイルの【ビットのチェック(単一)】ボタンを押してみてください。



'ビットのチェック(単一)
Private Sub CBtnChckBitOne_Click()
    Dim A As Byte
    Dim B As Byte
    Dim C As Byte
    
    A = 85
    B = 170
    C = &H80
    
    Debug.Print "A = " & A & vbTab & "(2進:" & BIN_STR(A) & ")"
    Debug.Print "B = " & B & vbTab & "(2進:" & BIN_STR(B) & ")"
    Debug.Print "C = " & C & vbTab & "(2進:" & BIN_STR(C) & ")"
    
    If A And C Then
        Debug.Print "Aは、8ビット目が立っています。"
    
    Else
        Debug.Print "Aは、8ビット目が立っていません。"
    
    End If
    
    If B And C Then
        Debug.Print "Bは、8ビット目が立っています。"
    
    Else
        Debug.Print "Bは、8ビット目が立っていません。"
    
    End If
    
End Sub


 実行結果は以下となり、ビットのチェックが出来ていることが分かります。



A = 85  (2進:01010101)
B = 170 (2進:10101010)
C = 128 (2進:10000000)
Aは、8ビット目が立っていません。
Bは、8ビット目が立っています。

 今度は、1つのビットだけでなく、複数のビットのチェックを行ってみたいと思います。チェック値は、チェックしたいビットを1にした値の論理和(Or)で作成します。この値と論理積Andを取ることで、複数ビットのチェックが可能になります。


 チェックの仕方によって、プログラムの実装が少し異なってきますの注意が必要です。複数ビットの全てが、立っているかどうかを、チェックしたいのであれば、論理積Andの結果が、チェックした値と同じかどうかをチェックします。複数ビットのいずれかが立っているかどうかを、チェックしたいのであれば、演算結果が単純に、0かそうでないかで判定します。

ビットのチェック(複数)


 チェック方法を簡潔に纏めると以下となります。



 以下のサンプルプログラムで上記が確認できます。少し、冗長的なプログラムになってしまいましたが、【ビットのチェック(複数)】ボタンを押下してみてください。


'ビットのチェック(複数)
Private Sub CBtnChckBitMulti_Click()
    Dim A As Byte
    Dim B As Byte
    Dim C As Byte
    Dim D As Byte
    
    A = 85
    B = 170
    C = &H80 Or &H40
    D = &H80 Or &H20
    
    Debug.Print "A = " & A & vbTab & "(2進:" & BIN_STR(A) & ")"
    Debug.Print "B = " & B & vbTab & "(2進:" & BIN_STR(B) & ")"
    Debug.Print "C = " & C & vbTab & "(2進:" & BIN_STR(C) & ")"
    Debug.Print "D = " & D & vbTab & "(2進:" & BIN_STR(D) & ")"
    
    '*** A ***
    '* C:6、8ビットが1*
    If (A And C) = C Then
        Debug.Print "Aは、チェックしたCの、全てのビットが立っています。"
        
    ElseIf A And C Then
        Debug.Print "Aは、チェックしたCの、いずれかのビットが立っています。"
        
    Else
        Debug.Print "Aは、チェックしたCの、ビットは立っていません。"
        
    End If
    
    '* D:7、8ビットが1 *
    If (A And D) = D Then
        Debug.Print "Aは、チェックしたDの、全てのビットが立っています。"
        
    ElseIf A And D Then
        Debug.Print "Aは、チェックしたDの、いずれかのビットが立っています。"
        
    Else
        Debug.Print "Aは、チェックしたDの、ビットは立っていません。"
        
    End If
    
    '*** B ***
    '* C:6、8ビットが1*
    If (B And C) = C Then
        Debug.Print "Bは、チェックしたCの、全てのビットが立っています。"
        
    ElseIf B And C Then
        Debug.Print "Bは、チェックしたCの、いずれかのビットが立っています。"
        
    Else
        Debug.Print "Bは、チェックしたCの、ビットは立っていません。"
        
    End If

    '* D:7、8ビットが1 *
    If (B And D) = D Then
        Debug.Print "Bは、チェックしたDの、全てのビットが立っています。"
        
    ElseIf B And D Then
        Debug.Print "Bは、チェックしたDの、いずれかのビットが立っています。"
        
    Else
        Debug.Print "Bは、チェックしたDの、ビットは立っていません。"
        
    End If
    
End Sub


 実行結果は以下となり、複数のビットのチェック動作が確認できました。



A = 85  (2進:01010101)
B = 170 (2進:10101010)
C = 192 (2進:11000000)
D = 160 (2進:10100000)
Aは、チェックしたCの、いずれかのビットが立っています。
Aは、チェックしたDの、ビットは立っていません。
Bは、チェックしたCの、いずれかのビットが立っています。
Bは、チェックしたDの、全てのビットが立っています。


 今回の豆知識は、以上で終了したいと思います。最初にも述べたのですが、ビット演算と聞くと、なんだか難しそうというイメージを持ちそうなのですが、単純な0と1の組合せによる演算ということが理解できれば、意外と、そうでもないのでは、ないでしょうか。もう少し、このビット演算について、お話したいことがありますので、それは、次回に持ち越したいと思います。



第8回  <  >  第10回



ダウンロード

 以下から、今回の豆知識で紹介した内容のエクセルファイルがダウンロードできます。

サンプルのダウンロード



2進、10進、16進値の変換

 2、10、16進値の相互変換はWindows標準アプリの電卓を利用すると簡単です。2のn乗を使った理論式を説明する、教科書本なども多くありますが、私は、この式を使って求めたことはありません。電卓を使いましょう

手順1 電卓の起動

 スタートメニューから電卓を起動します。

電卓の起動
※スタートメニューの中から、電卓のアイコンをクリックしてもOKです。


手順2 値の変換

 電卓の【メニュー】-【表示】-【プログラマ】を選択します。以下の各進数を切り替えることで、変換できます。数値のコピペ機能も使えます。

値の変換

連絡先

 ご意見・ご要望等ありましたら、画面最下部のメールアドレスまでご連絡ください。




エクセルバックアップ・ページのフッター
管理者のメールアドレス