始めに
近年のバージョンの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
↑↑↑↑↑↑↑ 編集リクエストの内容
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
↑↑↑↑↑↑↑ 編集リクエストの内容
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 - ネットワークエンジニアとして] (https://www.infraexpert.com/study/ip2.html)
-VBAでビット演算(論理演算) - t-hom's diary
-三流君ASP:2進数文字列と16進文字列の変換処理に挑戦
追記
nukie_53さんから
Array関数の引数には、ユーザー定義型以外の大体のものは指定できるため、直接数値を指定してもよいのではないでしょうか?
また、Array関数は、以下のようにOption Baseの影響を受けるためFor y = 0 To 3と決め打ちで書くのはちょっと怖い面があります。
下限が常に0になるVBA.Arrayを使用・・・すると、そのあたりの影響を無視できます。
とあります。試してみたところ、
'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
これでも動作しました。そちらの方がスマートなコードだと思います。ありがとうございました。