7,763
社区成员
发帖
与我相关
我的任务
分享
Option Explicit
Private Sub Command1_Click()
Dim A(2) As Currency
Dim shuzu() As Byte
Dim i As Integer, j As Integer
'两个测试用例
A(0) = Val("20190304123456")
A(1) = Val("20190118123456")
For j = 0 To 1
'调用转换
shuzu = Cur2Byte(A(j))
'结果验证
Debug.Print A(j)
For i = 1 To 8
Debug.Print i; shuzu(i), Hex(shuzu(i))
Next
Debug.Print "---------------"
Next
End Sub
'currency 转换为字节数组
Private Function Cur2Byte(ByVal curIn As Currency) As Byte()
'Dim A As Currency
Dim strHEX As String
Dim shuzu() As Byte
Dim i As Integer
'将currency转换为十六进制表示
strHEX = Cur2HEX(curIn)
'然后用0补到16位
strHEX = Replace(strHEX & Space(16 - Len(strHEX)), " ", "0")
'转换到字节数组
ReDim shuzu(1 To 8)
For i = 1 To 8
shuzu(i) = Val("&H" & Mid(strHEX, i * 2 - 1, 2))
Next
Cur2Byte = shuzu
End Function
'currency 转换为十六进制字符串
Private Function Cur2HEX(ByVal curIn As Currency) As String
Do
Cur2HEX = Right("0" & Hex(curIn - Fix(curIn / 256) * 256), 2) & Cur2HEX
curIn = Fix(curIn / 256)
Loop While curIn > 0
End Function
'currency 转换为十六进制字符串
Private Function Cur2HEX(ByVal curIn As Currency) As String
Do
Cur2HEX = Right("0" & Hex(curIn - Fix(curIn / 256) * 256), 2) & Cur2HEX
curIn = Fix(curIn / 256)
Loop While curIn > 0
End Function
这个函数我命名为currency to HEX 转换currency数据到十六进制。至于再转换为为BCD码的事情,由上一层函数再做一次转换。
转换为十六进制正常的思维是用楼上给出的链接里所述用curin逐次除以 16这个权值取余。这样每一次取余能够得到1位十六进制值(4bit),也就是0~F 。但我的思维跳了一下,当时脑袋里面以字节为单位在思考的,想每一次搞定8bit 也就是00~FF,所以也就是把输入数值转换为256进制的数,然后每个256进制的“位”再用HEX()函数转换成十六进制字符串。当然,VB里面的HEX函数是可以处理32bit数据的,只要你愿意,你也可以做4096、65536、1048576 …… 等数制的转换
好吧,不论你看到这里脑袋还清晰不清晰,我选择了做256进制的转换。
为了做这个转换,必须做循环取余,所以你看到了循环体。循环体里面的伪代码应该如下
do
余数 = 上一次循环处理后的整数商 mod 权值
hex(余数)转换为十六进制,取到若干位十六进制数
把取到的这些位拼接在输出结果上
整数商 = 上一次循环处理后的整数商 \ 权值
loop while 整数商 > 0
倒霉倒在currency太大,导致前面说的 取余mod计算溢出,所以要换一个方式取余数接下来就设计小学3年级的内容了:
因为:被除数 / 除数 = 整数商 .... 余数
所以:余数 =被除数 - 除数 * 整数商
这里被除数为 输入参数,除数为256进制的权值256
其中整数商相当于浮点商去除小数,在vb里有fix函数处理。
于是 整数商 = Fix(curIn / 256)
于是 有输入值针对256取余的操作: curIn - Fix(curIn / 256) * 256
取得的余数就是256进制数的“一个位”
这个数用hex函数取十六进制字符串 于是有了 : Hex(curIn - Fix(curIn / 256) * 256),
由于余数的取值范围是0~255,所以转换为十六进制表示就是0~FF 。
写到这里出现了个小问题,因为目标是要每次获得两个十六进制位,但是当余数小于16的时候hex函数返回的是一个字节,也就是我想要0A,可是它返回A 于是我们要对输出为1位的结果前面进行补“0”。
正常的思维是对这个输出的长度进行判断写个if条件分支。但是我在这里又进行了一次思维跳跃 :不论hex输出的是几位,我都在其左边添一个0,然后从右边取两位。也就是说输出可能形式是 “X” 和 "XX",补一个0以后 可能是 “0X”和“0XX”。右边取两位以后得到的就是“0X”和“XX”。
这个操作结合上面的代码加进来就有了 :Right("0" & Hex(curIn - Fix(curIn / 256) * 256), 2)
我们一次性得到了十六进制的两个位,把它拼接到输出变量上,于是有了: Right("0" & Hex(curIn - Fix(curIn / 256) * 256), 2) & Cur2HEX
由于是循环拼接,于是有了:Cur2HEX = Right("0" & Hex(curIn - Fix(curIn / 256) * 256), 2) & Cur2HEX
这一行代码解决了伪代码循环体中的三行,同时还处理了伪代码中没有写出来的格式整理问题。
说实在的,这样写并不好,大大增加了其他人理解代码的难度。这仅仅是为了快速回帖。
接下来是伪代码循环体中的第四行,取整数商。32bit内可以用 \运算符处理,32bit以上的数据 用普通除法去除小数取整的方式获得。
于是有了 curIn = Fix(curIn / 256)
我用输入参数变量作为数据处理过程中的中间变量。其实这个做法是很不利于代码解读的,而且前提是函数声明中输入参数为byval 。不要学我这么干,我只是偷懒。
至此,你提取出来的那两行解释完毕。
Private Sub Command1_Click()
Dim A As Currency
A = Val("20190304123456")
Debug.Print Cur2HEX(A)
A = Val("20190118123456")
Debug.Print Cur2HEX(A)
End Sub
Private Function Cur2HEX(ByVal curIn As Currency) As String
Do
Cur2HEX = Right("0" & Hex(curIn - Fix(curIn / 256) * 256), 2) & Cur2HEX
curIn = Fix(curIn / 256)
Loop While curIn > 0
End Function
curIn - Fix(curIn / 256) * 256 把商去除小数取整再乘以除数,再拿被除数减一下就是余数了。
由于这个余数小于256,所以hex不会溢出。
又由于hex出来的结果不会自动补0所以
Right("0" & hex(XX) ,2) 把hex的结果在左边补个0,再从右边取2位,当结果为1位的时候前面补的0会一起截出来,如果结果是2位,那么前面的那个0不会有影响。