LoginSignup
2
1

More than 3 years have passed since last update.

VBAのみで2進数と16進数を互いに変換してみる。

Last updated at Posted at 2018-10-19

始めに

近年のバージョンのExcelには16進数表記を2進数表記に変換するHEX2BIN関数や、2進→16進変換をするBIN2HEX関数がありますが、Accessなどにはないの作ってみました。公開して需要があるのか解りませんが、VB系には汎用性が有ると思うのでメモ替わりに公開してみます。

16進←→2進ってどうやるんだっけ?

コンピューターにおいて二進と十六進の変換は基本中の基本だと思いますが、一応おさらいを。

2進から16進

11010010という数を例にして見ると、まず2進の数を4桁毎に分解します。この場合は1101と0010です。
続いて下の表に従い1の数のところだけ足します。

1 1 0 1
8 4 2 1
0 0 1 0
8 4 2 1

つまり、8+4+1で13です。つぎの2桁は0010なので2です。そうして得られた結果の下の対処表に当てはめれば
11010010の答えがD2であることがわかります。

1 2 3 4 5 6 7 8 9 A B C D E F
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

表1:10進と16進の対照表

16進から2進

今度は逆の操作ですが、一桁ずつ算定していきます。D2の場合はDと2に分解し、以下の表に当てはめましょう。

1 2 3 4 5 6 7 8 9 A B C D E F
0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

表2:16進と2進の対照表

Dは1101、2は10なので0010。これを合成すると11010010となります。

実装

16進変換はHEX関数があるのでそれを利用すれば容易にもとめられるのですが、2進にはそんな便利な関数はないので、配列に結果を格納しておいて、11なら「1011を格納したarrBin(11)」を当てはめるというやり方を考えましたし、実際そういう実装をされている方 もいらっしゃったのですが、スマートじゃないのでビット演算で求めることにしました。

解説

どちらともvarBinaryに、若い順番から8,4,2,1を格納し、1(または4)文字取り出し演算を繰り返すシンプルな実装となりました。
varBinaryはVariant型なので念のためCLng関数で変換しています。

16進変換のソースコード

↓↓↓↓↓↓↓ あなたの記事の内容
VB:Bin_2_Hex
───────
vb:Bin_2_Hex
↑↑↑↑↑↑↑ 編集リクエストの内容
Const strBin As String = "11010010"

Dim i           As Long
Dim y           As Long
Dim lack        As Long
Dim tmp         As String
Dim lngByte     As Long
Dim strAns      As String
Dim varBinary   As Variant

varBinary = Array("8", "4", "2", "1")

lack = 4 - (Len(strBin) Mod 4)

If lack <> 4 Then
    Do Until lack = 0
        strBin = "0" & strBin
        lack = lack - 1
    Loop
End If



For i = 1 To Len(strBin) Step 4

    lngByte = 0    '変数の初期化
    tmp = Mid(strBin, i, 4) '値を取り出す

    For y = 0 To 3
        '数を取り出しフラグが立っていると足す
        If Mid(tmp, y + 1, 1) = "1" Then
            lngByte = lngByte + CLng(varBinary(y))
        End If
    Next y

    strAns = strAns & Hex(lngByte) '答えを格納する
Next i

Debug.Print "答え:" & strAns
追記:最初のコードでは4の倍数ではない数では誤った値が出るので修正しました。

###2進変換のソースコード

↓↓↓↓↓↓↓ あなたの記事の内容
```VB:Hex_2_Bin
───────
```vb:Hex_2_Bin
↑↑↑↑↑↑↑ 編集リクエストの内容
    Const strHex As String = "F2"

    Dim i           As Long
    Dim y           As Long
    Dim tmp         As Long
    Dim strAns      As String
    Dim varBinary   As Variant

    varBinary = Array("8", "4", "2", "1")

    For i = 1 To Len(strHex)
        tmp = CLng("&h" & Mid(strHex, i, 1))  '値を取り出す

        For y = 0 To 3
            '数を取り出しフラグが立っていると足す
            If (tmp And CLng(varBinary(y))) = 0 Then
                strAns = strAns & "0"
            Else
                strAns = strAns & "1"
            End If
        Next
    Next i

    Debug.Print "答え:" & strAns

終わりに

あまりに基礎的なコードであるがゆえにあまりサンプルも載っていなかったこともあり投稿させていただきました。一つでも参考になれれば幸いです。

参考サイト

-2進数 & 10進数 & 16進数 - Part 2 - ネットワークエンジニアとして
-VBAでビット演算(論理演算) - t-hom's diary
-三流君ASP:2進数文字列と16進文字列の変換処理に挑戦

追記

nukie_53さんから

Array関数の引数には、ユーザー定義型以外の大体のものは指定できるため、直接数値を指定してもよいのではないでしょうか?
また、Array関数は、以下のようにOption Baseの影響を受けるためFor y = 0 To 3と決め打ちで書くのはちょっと怖い面があります。
下限が常に0になるVBA.Arrayを使用・・・すると、そのあたりの影響を無視できます。

とあります。試してみたところ、

newcode
'16進に変換
Sub Bin_2_Hex()
    Const strBin As String = "11010010"

    Dim i           As Long
    Dim y           As Long
    Dim tmp         As String
    Dim lngByte     As Long
    Dim strAns      As String
    Dim varBinary   As Variant

    varBinary = VBA.Array(8&, 4&, 2&, 1&)

    For i = 1 To Len(strBin) Step 4

        lngByte = 0    '変数の初期化
        tmp = Mid(strBin, i, 4) '値を取り出す

        For y = 0 To 3
            '数を取り出しフラグが立っていると足す
            If Mid(tmp, y + 1, 1) = "1" Then
                lngByte = lngByte + varBinary(y)
            End If
        Next y

        strAns = strAns & Hex(lngByte) '答えを格納する
    Next i

    Debug.Print "答え:" & strAns

End Sub

'2進に変換

Sub Hex_2_Bin()
 Const strHex As String = "F2"

    Dim i           As Long
    Dim y           As Long
    Dim tmp         As Long
    Dim strAns      As String
    Dim varBinary   As Variant

    varBinary = VBA.Array(8&, 4&, 2&, 1&)

    For i = 1 To Len(strHex)
        tmp = CLng("&h" & Mid(strHex, i, 1))  '値を取り出す

        For y = 0 To 3
            '数を取り出しフラグが立っていると足す
            If (tmp And varBinary(y)) = 0 Then
                strAns = strAns & "0"
            Else
                strAns = strAns & "1"
            End If
        Next
    Next i

    Debug.Print "答え:" & strAns
End Sub

これでも動作しました。そちらの方がスマートなコードだと思います。ありがとうございました。

2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1