Khi chúng tôi giải quyết bài toán truyền tin trong oto, cần tính toán CRC, đã gặp bài toán như sau:
Việc chuyển dãy nhị phân thành hệ 16 hexa đã gặp vấn đề tràn số.
Trong VBA excel đã có hàm WorksheetFunction.Bin2Hex , tuy nhiên nếu input là một dãy nhị phân có độ dài là 64 (gồm 64 ký tự 1 hoặc 0: 1001010101...101), thì
hàm này không xử lý được.
Nếu theo cách nghĩ thông thường:
Dãy nhị phân -> Chuyển đổi thành số thập phân (hệ cơ số 10) -> Chuyển đổi sang hệ 16.
Chúng ta sẽ gặp vấn đề tràn số ở bước dưới đây khi dãy nhị phân có độ dài quá lớn:
Dãy nhị phân -> Chuyển đổi thành số thập phân (hệ cơ số 10)
Nhằm khắc phục điều này, ta cần xây dựng thuật toán mới và hàm riêng để chuyển đổi dãy nhị phân sang hệ 16 với độ dài nhị phân không hạn chế.
Xét ví dụ dưới đây:
1111 1101(b) = 0xFD
Ta có \[ 2^4=16 \].
Một chữ số trong hệ 16 là: 0,1,2,…,D,E,F có giá trị từ 0 tới 15 trong hệ cơ số 10.
Như vậy bất cứ một chữ số trong hệ 16 nào cũng có thể được biểu diễn bởi một dãy nhị phân có độ dài là 4.
Ta ví dụ:
15 = 0xF = 1111(b)
14 = 0xE = 1110(b)
…
0 = 0x0 = 0000(b)
Nói như vậy, nếu ta có một dãy nhị phân có độ dài vô cùng, ta chỉ việc tách thành từng đoạn có độ dài là 4 rồi chuyển sang hệ 16. Ví dụ:
1111 1101(b)
Ta thực hiện tách dãy nhị phân thành từng đoạn có độ dài là 4:
1111(b) = 0xF
1101(b) = 0xD
Nên: 1111 1101(b) = 0xFD
Từ đó ta xây dựng được hàm như sau:
Mặc dù trong hàm trên ta sử dụng WorksheetFunction.Bin2Hex, nhưng đầu vào của hàm này là chuỗi nhị phân có độ dài là 4, cho nên sẽ không có tràn số xảy ra.
Tuy nhiên vì hàm này nhận dãy nhị phân có độ dài là bội của 4. Nếu dãy nhị phân có độ dài là 2: 10 hoặc 3: 111, hoặc 7: 1011011 thì sẽ không thực hiện được.
Vì vậy ta cần chèn các số 0 vào trước đó.
Ví dụ: 10 -> 0010, 111 -> 0111, 1011011 -> 01011011
Và bây giờ ta có hàm chuyển đổi dãy nhị phân sang hệ hexa không bị hạn chế bởi độ dài dãy nhị phân, cũng như không cần quan tâm độ dài nhị phân có là bội của 4 hay không:
Việc chuyển dãy nhị phân thành hệ 16 hexa đã gặp vấn đề tràn số.
Trong VBA excel đã có hàm WorksheetFunction.Bin2Hex , tuy nhiên nếu input là một dãy nhị phân có độ dài là 64 (gồm 64 ký tự 1 hoặc 0: 1001010101...101), thì
hàm này không xử lý được.
Nếu theo cách nghĩ thông thường:
Dãy nhị phân -> Chuyển đổi thành số thập phân (hệ cơ số 10) -> Chuyển đổi sang hệ 16.
Chúng ta sẽ gặp vấn đề tràn số ở bước dưới đây khi dãy nhị phân có độ dài quá lớn:
Dãy nhị phân -> Chuyển đổi thành số thập phân (hệ cơ số 10)
Nhằm khắc phục điều này, ta cần xây dựng thuật toán mới và hàm riêng để chuyển đổi dãy nhị phân sang hệ 16 với độ dài nhị phân không hạn chế.
Bạn cần đăng nhập để thấy đính kèm
Xét ví dụ dưới đây:
1111 1101(b) = 0xFD
Ta có \[ 2^4=16 \].
Một chữ số trong hệ 16 là: 0,1,2,…,D,E,F có giá trị từ 0 tới 15 trong hệ cơ số 10.
Như vậy bất cứ một chữ số trong hệ 16 nào cũng có thể được biểu diễn bởi một dãy nhị phân có độ dài là 4.
Ta ví dụ:
15 = 0xF = 1111(b)
14 = 0xE = 1110(b)
…
0 = 0x0 = 0000(b)
Nói như vậy, nếu ta có một dãy nhị phân có độ dài vô cùng, ta chỉ việc tách thành từng đoạn có độ dài là 4 rồi chuyển sang hệ 16. Ví dụ:
1111 1101(b)
Ta thực hiện tách dãy nhị phân thành từng đoạn có độ dài là 4:
1111(b) = 0xF
1101(b) = 0xD
Nên: 1111 1101(b) = 0xFD
Từ đó ta xây dựng được hàm như sau:
Mã:
'Input: 11111101
'Output: FD
'Input: 1120
'Output: CanNotCalculator
Function bin2hexsub(ByVal s4 As String) As String
Dim i As Integer
Dim cnt As Integer
Dim temp As String
Dim c As String
Dim out As String
bin2hexsub = ""
out = ""
If Len(s4) = 0 Then
bin2hexsub = "0"
Exit Function
Else
cnt = 0
temp = ""
For i = 1 To Len(s4) Step 1
c = Mid(s4, i, 1)
If InStr(1, "01", c) = 0 Then
bin2hexsub = "CanNotCalculator"
Exit Function 'Phat hien khong phai la day nhi phan. c khong phai la 1 hoac 0
End If
cnt = cnt + 1
temp = temp & c
If cnt = 4 Then
out = out & WorksheetFunction.Bin2Hex(temp)
temp = ""
cnt = 0
End If
Next i
End If
bin2hexsub = out
End Function
Tuy nhiên vì hàm này nhận dãy nhị phân có độ dài là bội của 4. Nếu dãy nhị phân có độ dài là 2: 10 hoặc 3: 111, hoặc 7: 1011011 thì sẽ không thực hiện được.
Vì vậy ta cần chèn các số 0 vào trước đó.
Ví dụ: 10 -> 0010, 111 -> 0111, 1011011 -> 01011011
Và bây giờ ta có hàm chuyển đổi dãy nhị phân sang hệ hexa không bị hạn chế bởi độ dài dãy nhị phân, cũng như không cần quan tâm độ dài nhị phân có là bội của 4 hay không:
Mã:
'Input: 11111
'Output: 1F
'Input: 11201
'Output: CanNotCalculator
Function bin2hexmain(ByVal s As String) As String
Dim i As Integer
Dim n As Integer
Dim s4 As String
n = Len(s) Mod 4
If n = 0 Then
bin2hexmain = bin2hexsub(s)
Else
s4 = ""
For i = 1 To 4 - n Step 1
s4 = s4 & "0"
Next i
s4 = s4 & s
bin2hexmain = bin2hexsub(s4)
End If
End Function