リストHOME  リストOpen Source

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

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

 第10回も、前回に引き続き、VBAでの論理演算子を使ったビット演算について、解説したいと思います。 今回、お話する内容は、主に以下の3つです。



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


Xor演算

 まずXor演算の真理値を以下に示します。Xor演算は、A、Bのどちらかが1の時に1、AとBが同じ時は、0になります。


Xor演算


 このXor演算、実は非常に面白い特徴があります。それは、同じ値で、Xor演算を2回行うと値が、元に戻るというものです。以下にその演算の例を示します。

Xor演算の例


 ちょっとした、暗号/復号化といったところでしょうか。AをBでXor演算することで、Aがまったく異なる値に変換され、もう一度、BでXor演算すると、元の値Aに戻るというものです。


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



'Xor演算
'2回同じ値でXorをとると値が、元に戻ります。
Private Sub CBtnXor_Click()
    Dim A As Byte
    Dim B As Byte
    Dim C As Byte
    
    A = 170
    B = 100
    
    Debug.Print "A=" & A & "(2進:" & BtValueToStringByte(A) & ")"
    Debug.Print "B=" & B & "(2進:" & BtValueToStringByte(B) & ")"
    
    'Xor演算 1回目
    C = A Xor B
    
    Debug.Print "1回目 A Xor B =" & C & "(2進:" & BtValueToStringByte(C) & ")"

    'Xor演算 2回目
    A = C Xor B
    
    '同じ値でXor演算を2回行うと、値が元に戻ります。
    Debug.Print "2回目 C Xor B =" & A & "(2進:" & BtValueToStringByte(A) & ")"
    
End Sub


 実際に、【Xor演算】ボタンを押した時の、出力結果が以下です。Xor演算を2回実施することで、値が元に戻ることが確認できます。



A=170(2進:10101010)
B=100(2進:10100100)
1回目 A Xor B =206(2進:01010010)
2回目 C Xor B =170(2進:10101010)


 上記の性質を利用した、Xor演算を使ったプログラムをもう一つだけ、紹介したいと思います。ボタンを押下するたびに、TrueとFalseが、トグルに変わるといったものです。これは、サンプルの【Xor演算(トグル)】を押すと実行できますので、確認してみてください。



Private ToggleFlg As Boolean

'Xor演算(トグル)
Private Sub CBtnToggle_Click()
    '値が交互に変わります。
    ToggleFlg = ToggleFlg Xor True
    
    If ToggleFlg Then
        Debug.Print " Trueです。"
        
    Else
        Debug.Print " Falseです。"
        
    End If
    
End Sub


符号ビット

 データのビットを考える上で、重要な概念に符号ビットと言われるものがあります。このビットは、そのデータの値の正負(プラス、マイナス)を表すビットで、最上位ビットが符号ビットとなります。データには、幾つか型がありますが、この符号ビットを持っている(持っていない)型のことを、符号有り(無し)と呼んでいます。
 以下に、VBAでよく使用される代表的な、整数値のデータ型について、表に示します。


代表的な整数値のデータ型
データ型符号データの範囲
Byte型符号無し0~255
Integer型符号有り-32768~32767
Long型符号有り-2147483648~2147483647



 それでは、サンプルプログラムで符号ビットを確認してみましょう。サンプルファイルの【符号ビット】ボタンを押下すると以下の、プログラムが実行されます。これは、10進値の-100、Integer型の変数Aと、Long型の変数Bに-100を代入して、2進値表示する処理内容となっています。



'符号ビット
Private Sub CBtnSigned_Click()
    Dim A As Integer
    Dim B As Long
    
    A = -100        'Integer型
    B = -100        'Long型
    
    Debug.Print "A=" & A & "(2進:" & BtValueToStringInteger(A) & ")"
    Debug.Print "B=" & B & "(2進:" & BtValueToStringLong(B) & ")"
    
End Sub


 上記の処理を実行すると結果は以下となります。Integer型、Long型ともに、符号ビットである最上位ビットが1になっていることが分かります。


 同じ-100という値なのですが、2進表示すると違う値に見えてしまいますね。この違いは、データの型(サイズ)が違うところにあります。この値をIf(A=B)文で判定すると、いずれも同じ-100として判定されます。これは、コンパイラが型の違いを考慮して、数値として比較しているため、そうなります。



A=-100(2進:1111111110011100)
B=-100(2進:11111111111111111111111110011100)


 ちなみに、-1は、Long型が&HFFFFFFFF(16進)で、Integer型が&HFFFF(16進)で、いずれもすべてのビットが1となります。数学的には、&HFFFFFFFFと&HFFFFは同じではないのですが、プログラムでは、同じ値-1となります。


 また、正の値を、負の値に、論理演算で変換する場合は、以下のようにします。



    Dim v As Long

    v = 100

    'vを-100にするには、100から1を引いて反転させます。
    v = Not (v - 1)

    Debug.Print v

 ですので、逆に、負の値を、正の値に変換する場合は、以下となります。



    v = (Not v) + 1


ビットシフト

 次に、ビットシフトと呼ばれるビット演算処理について説明します。ビットシフトとは、その名の通り、ある値をビット単位で、値をシフトする処理のことです。以下に、例として、ある値を100とした場合のビットシフトについて、示します。

ビットシフトの例


 では、このビットシフト処理なのですが、VBAのプログラムで、一体どのように実装すればよいか分かりますでしょうか?


 10進数の値を1桁繰り上げるには、×10、1桁繰り下げるには、÷10、すれば良いのは簡単に分かりますね。これと、一緒で、2進数を1桁(ビット)繰り上げるには、×2、1桁(ビット)繰り下げるには、÷2すれば、ビットシフトできます。ですので、3ビット右にシフトするのであれば、8(2の3乗)で割ります。また、5ビット左にシフトするのであれば、32(2の5乗)倍すれば、ビットシフトできます。


 基本的な、ビットシフトの考え方はこれでOKなのですが、プログラムでは、少し注意が必要です。


 一つは、VBAでは、データ型のサイズを上回る演算は、オーバーフローしてしまいます。ですので、左にシフトする場合には、オーバーフローしないように、一工夫してやらなければ、なりません。


 その例が以下です。

オーバーフローの回避


 もう一つの注意点は、符号有りのデータ型のシフトについてです。右に1ビットシフトする場合を考えます。正の値を2で割ると、最上位ビットは0になりますが、負の値を2で割ると、最上位ビットが1になります。負の値を2で割った時の演算結果は、負の値となりますので、符号ビットが1になるのは、当然といえば当然なのですが、元の値によって、最上位ビットに入ってくる値が変わってくる点に、ビットシフトという意味では、少し違和感を感じてしまうかも知れません。

符号ありの右ビットシフト


 また、ある値を2で割ると、基本的には、右に1ビットシフトするのですが、値が-1のときに注意が必要です。-1は2で割ると、0.5になりますが、元の値が、整数型であれば、少数点部分は切り捨てられ、0になってしまいます。


 例えば、Integer型の-1(&HFFFF)ですが、この値を、右に1ビットシフトさせたときに、結果が0になってしまっては、ビットシフトという点では、おかしいですよね。数値演算としては、0となることで正しいのですが、ビットシフトとしては、符号ビットに1が入り、-1にならなければなりません。

-1右ビットシフト


 ですので、値が-1のときに、右にビットシフトする場合は、全て、-1になるようにプログラミングしてやらなければなりません。


 サンプルファイルに、ビットシフトのサンプルを実装していますので、【ビットシフト】ボタンを押して、確認してみてください。



第9回  <  >  第11回



ダウンロード

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

サンプルのダウンロード



連絡先

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




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