VB6 没有整形变量可以存放 2,147,483,647 以上的数字,现在遇到一问题是 某物品编码为14位,如何将这个14位的存放到一6字节数组中,谢谢大家

eisldkw 2019-05-05 02:08:02
VB6 没有整形变量可以存放 2,147,483,647 以上的数字,现在遇到一问题是 某物品编码为14位,如何将这个14位的数值按其在内存中的存放方式,存放到一8字节数组中,谢谢大家
...全文
1552 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
eisldkw 2020-06-03
  • 打赏
  • 举报
回复
引用 35 楼 脆皮大雪糕 的回复:
按照你给的用例,是补到最后。

看你在8楼给的用例
20190304123456 16进制为 125CEBE7BA40 存放为
shuzu(1)=&h12
shuzu(2)=&h5C
shuzu(3)=&hEB
shuzu(4)=&hE7
shuzu(5)=&hBA
shuzu(6)=&h40
shuzu(7)=&h0
shuzu(8)=&h0

补成 125CEBE7BA400000


非常感谢。请问您这算法 能用到 变量为 DOUBLE的类型吗
亚纹 2019-05-10
  • 打赏
  • 举报
回复
引用 楼主 eisldkw 的回复:
如何将这个14位的数值按其在内存中的存放方式,存放到一8字节数组中

引用 8 楼 eisldkw 的回复:
如 20190304123456 16进制为 125CEBE7BA40 存放 指令数组为
shuzu(1)=&h12
shuzu(2)=&h5C
shuzu(3)=&hEB
shuzu(4)=&hE7
shuzu(5)=&hBA
shuzu(6)=&h40
shuzu(7)=&h0
shuzu(8)=&h0

楼主开头不是说内存中的存放方式存放到数组中么 windows 是小端模式 应该是
shuzu(1)=&h40
shuzu(2)=&hBA
shuzu(3)=&hE7
shuzu(4)=&hEB
shuzu(5)=&h5C
shuzu(6)=&h12
shuzu(7)=&h0
shuzu(8)=&h0
你的是大端模式 纯属抬杠
另 有两位大神这么细致的给你讲解 真是荣幸啊
eisldkw 2019-05-10
  • 打赏
  • 举报
回复
引用 35 楼 脆皮大雪糕 的回复:
按照你给的用例,是补到最后。

看你在8楼给的用例
20190304123456 16进制为 125CEBE7BA40 存放为
shuzu(1)=&h12
shuzu(2)=&h5C
shuzu(3)=&hEB
shuzu(4)=&hE7
shuzu(5)=&hBA
shuzu(6)=&h40
shuzu(7)=&h0
shuzu(8)=&h0

补成 125CEBE7BA400000


好的。感谢。
舉杯邀明月 2019-05-10
  • 打赏
  • 举报
回复
从“值转换”来说,补0肯定是补在左边(高位);而按“实际应用”来说,其实关系不大。

按楼主的应用环境: 14位编码(10进制数值)
从最小值“1加13个0”到最大值“14个9”,转换成“真16进制”之后,都是占6字节。
 即:14位的10进制编码,总是12位的16进制(含高位补0)。
因此始终都是“补2字节0”(16进制为4个0),
 只要统一规则,补左、补右、或者不补,都没什么影响。



引用 33 楼 脆皮大雪糕 的回复:
[quote=引用 32 楼 eisldkw 的回复:]

非常感谢,您的详细解读,通过本贴,我经过反复的思考,终于彻底明白了,进制转换时,为什么要除16 取余 而后将余数 取倒序,非常感谢大家。


感慨那么多还不如赶紧结贴[/quote]
eisldkw 2019-05-10
  • 打赏
  • 举报
回复
非常感谢,脆皮大雪糕 舉杯邀明月 ,结贴喽
eisldkw 2019-05-09
  • 打赏
  • 举报
回复
引用 30 楼 脆皮大雪糕 的回复:
[quote=引用 29 楼 eisldkw 的回复:]

非常感谢,我来做一下注解,您看我的理解 对不对

Cur2HEX = Right("0" & Hex(curIn - Fix(curIn / 256) * 256), 2) & Cur2HEX
curIn = Fix(curIn / 256)

这个算法的来历

比如 &H 12 34 AB CD EF 这个数,
&H12 肯定是 低 4字节 上 全加满 即 全为FF FF FF FF 后再加1 加上来的,已经满了 &H12 次 &H FF FF FF FF
而&H 34 AB CD EF 部分 是加了 &H 12 次 &H FF FF FF FF 后 又加的值
同理 &H 34 AB CD EF 说明 这个数中 低3字节 已经加满了 &H34 次 &H FF FF FF 次后 又加了 &H AB CD EF
以此类推


没那么复杂,其实就是十进制转换成其他进制时的标准取余算法
比如要转换成K进制,K就是目标数制的权。那么接下来就是不断的除以这个权值取余数…… 好吧,描述起来比较麻烦,看下面这个链接吧
https://baijiahao.baidu.com/s?id=1621423277747819472&wfr=spider&for=pc

在你的这个需求里面会遇到一个问题,由于你的数值比较大,VB的取余mod计算超过32bit的数据会溢出,整除\计算也会溢出 但是普通除法以及去除小数取整fix运算没问题。所以要用曲线救国的方式进行超过32bit的数值进行取余操作。

其实我的代码下面已经对这段进行了专门的注释。
引用 21 楼 脆皮大雪糕 的回复:
curIn - Fix(curIn / 256) * 256 把商去除小数取整再乘以除数,再拿被除数减一下就是余数了。
由于这个余数小于256,所以hex不会溢出。
又由于hex出来的结果不会自动补0所以
Right("0" & hex(XX) ,2) 把hex的结果在左边补个0,再从右边取2位,当结果为1位的时候前面补的0会一起截出来,如果结果是2位,那么前面的那个0不会有影响。

[/quote]

非常感谢,您的详细解读,通过本贴,我经过反复的思考,终于彻底明白了,进制转换时,为什么要除16 取余 而后将余数 取倒序,非常感谢大家。
脆皮大雪糕 2019-05-09
  • 打赏
  • 举报
回复
按照你给的用例,是补到最后。 看你在8楼给的用例 20190304123456 16进制为 125CEBE7BA40 存放为 shuzu(1)=&h12 shuzu(2)=&h5C shuzu(3)=&hEB shuzu(4)=&hE7 shuzu(5)=&hBA shuzu(6)=&h40 shuzu(7)=&h0 shuzu(8)=&h0 补成 125CEBE7BA400000
eisldkw 2019-05-09
  • 打赏
  • 举报
回复
引用 33 楼 脆皮大雪糕 的回复:
[quote=引用 32 楼 eisldkw 的回复:]

非常感谢,您的详细解读,通过本贴,我经过反复的思考,终于彻底明白了,进制转换时,为什么要除16 取余 而后将余数 取倒序,非常感谢大家。


感慨那么多还不如赶紧结贴[/quote]

非常感谢,问题是,我测试了一下,大神,第二套代码中

strHEX = Replace(strHEX & Space(16 - Len(strHEX)), " ", "0")

这补0应该补到左侧,而不是右侧吧



脆皮大雪糕 2019-05-09
  • 打赏
  • 举报
回复
引用 32 楼 eisldkw 的回复:
非常感谢,您的详细解读,通过本贴,我经过反复的思考,终于彻底明白了,进制转换时,为什么要除16 取余 而后将余数 取倒序,非常感谢大家。
感慨那么多还不如赶紧结贴
脆皮大雪糕 2019-05-08
  • 打赏
  • 举报
回复
不需要搞那么复杂,就是把我两次给的代码合并起来,第二次给的转换函数替换投机取巧的那行。 得了,整理一下,给你一个我认为比较优雅的方式吧 新建窗体,放一个按钮,然后粘贴下面代码试一试。

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



eisldkw 2019-05-08
  • 打赏
  • 举报
回复
大神,我补充后的代码如下:
Dim A As Currency

Dim cur2hex As String
Dim shuzu() As Byte
Dim i As Integer
'十进制字符串转换为十进制数值
A = Val("20190304123456")
A = Val("1250909226070") '对应16进制 12340000456

A = Val(Trim(Text1.Text))
Dim B As String, C As String 'B 存放高位部分 ,C 存放 低位部分

B = Hex(Int(A / &H10000000))
C = Hex(A - (Int(A / &H10000000) * &H10000000))

B = Hex(Int(A / &H10000000))
C = Hex(A - (Int(A / &H10000000) * &H10000000))


' 将 B C 均左 补 0 凑到 7位

Select Case Len(B)
Case 0
B = "0000000"
Case 1
B = "000000" & B
Case 2
B = "00000" & B
Case 3
B = "0000" & B
Case 4
B = "000" & B
Case 5
B = "00" & B
Case 6
B = "0" & B
Case 7
B = B
End Select

Select Case Len(C)
Case 0
C = "0000000"
Case 1
C = "000000" & C
Case 2
C = "00000" & C
Case 3
C = "0000" & C
Case 4
C = "000" & C
Case 5
C = "00" & C
Case 6
C = "0" & C
Case 7
C = C
End Select

Text2.Text = B
Text3.Text = C

'投机取巧的办法一行代码把currency转换为十六进制字符串
cur2hex = Hex(Int(A / &H10000000)) & Hex(A - (Int(A / &H10000000) * &H10000000))

Text4.Text = cur2hex

Text5.Text = B & C & " " & B & " " & C
' Text6.Text = Hex(A)

'如果结果是奇数个字符那么前面要补一个0
If Len(cur2hex) Mod 2 = 1 Then cur2hex = "0" & cur2hex
'然后用0补到16位
cur2hex = Replace(cur2hex & Space(16 - Len(cur2hex)), " ", "0")
Debug.Print cur2hex '打印出来确认一下是否正确
'转换到字节数组
ReDim shuzu(1 To 8)
For i = 1 To 8
shuzu(i) = Val("&H" & Mid(cur2hex, i * 2 - 1, 2))
Next


'*******结果验证********

For i = 1 To 8
Debug.Print i; shuzu(i), Hex(shuzu(i))
Next

eisldkw 2019-05-08
  • 打赏
  • 举报
回复
引用 21 楼 脆皮大雪糕 的回复:
还是老老实实写十六进制转换函数吧,不要投机取巧。由于hex、mod都只能处理4字节的整数,currency算的时候会溢出,所以要有一些变通的法子来取余


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不会有影响。


非常感谢,以下是我在 大神 代码 基础 上略做补充 后的代码, 肯 请大神给 批阅一下。
eisldkw 2019-05-08
  • 打赏
  • 举报
回复
引用 19 楼 舉杯邀明月 的回复:
[quote=引用 18 楼 eisldkw 的回复:]
[quote=引用 17 楼 舉杯邀明月 的回复:]
[quote=引用 15 楼 eisldkw 的回复:]
[quote=引用 10 楼 脆皮大雪糕 的回复:]

Dim A As Currency
Dim cur2hex As String
Dim shuzu() As Byte
Dim i As Integer
'十进制字符串转换为十进制数值
A = Val("20190304123456")
'投机取巧的办法一行代码把currency转换为十六进制字符串
cur2hex = Hex(Int(A / &H10000000)) & Hex(A - (Int(A / &H10000000) * &H10000000))

'如果结果是奇数个字符那么前面要补一个0
If Len(cur2hex) Mod 2 = 1 Then cur2hex = "0" & cur2hex
'然后用0补到16位
cur2hex = Replace(cur2hex & Space(16 - Len(cur2hex)), " ", "0")
Debug.Print cur2hex '打印出来确认一下是否正确
'转换到字节数组
ReDim shuzu(1 To 8)
For i = 1 To 8
shuzu(i) = Val("&H" & Mid(cur2hex, i * 2 - 1, 2))
Next


'*******结果验证********

For i = 1 To 8
Debug.Print i; shuzu(i), Hex(shuzu(i))
Next




非常非常非常的感谢,还有一个问题,为什么是除以 &H10 00 00 , 而不是除以 其他数值?非常感谢。[/quote]
实际上,完全可以选其它数值,关键是要“合理”。
你的“14位10进制数”,转换成“2进制”,基本就是在6字节左右。
 对应的“16进制”,就是大约在“12位16进制”左右了。
把这个“编码值”除以一个合适的系数(必须为 2^n ,n取个“合理”的值),
 可把这“12位左右的16进制”分成“两段”,让它们都不超过&H7FFFFFFF ,
 就可以直接用Hex函数转换和联接了。

不过10楼的代码是有Bug的,有时候转换结果不正确。
比如2019年1月18号之前的编码,可能就错了。
比如: 20190118123456
 10的结果是 0125CED197C0
其实正确值是 125CE0D197C0
你可以用系统的“计算器”转换来看。
这个“补位”应该是在 每个Hex函数结果之后在“高位”补0,
 而不是把两个Hex结果“连接”之后,再去按长度补0
[/quote]

非常感谢,也是大神级的人物。由您的讲解,我感觉 有可能 当 (A - (Int(A / &H10000000) =1时,我们想要的HEX码为 000001 但Hex(A - (Int(A / &H10000000))得到的结果为 1,还会差5个0,不是在开头补一个0 所能解决的。不知道对不对。谢谢。[/quote]

不是差5个,是差6个。
你注意一下,10楼的代码,系数是 &H10000000 ,这后面是“7个0”,
 这样“低段16进制数”就是7位。
而你看成“6位”了 …………

按你在15楼说的,&H10 00 00,则是“5位”,这样“低段”分得太少,
 必然“高段”位数就较多,有“高段”部分出现溢出的风险。

对了,还有一个要注意的,就是这种方法要直接利用Hex函数的结果来拼接,
我在17楼说的 2^n 系数,这个 n值还不能随意选,必须是4的倍数才行。
这种方法,系数值对应的16进制,只能是:&H10、&H100、&H1000……、&H10000000
 这“有限”的7个数。

[/quote]

非常感谢,但我感觉 “ n值还不能随意选,必须是4的倍数才行4的倍数”这个说法好象不对,应该是16的位数,即最小是F所占用的4个BIT位,

以下是我修整后的代码,请帮忙看一下,

Dim A As Currency

Dim cur2hex As String
Dim shuzu() As Byte
Dim i As Integer
'十进制字符串转换为十进制数值
A = Val("20190304123456")
A = Val("1250909226070") '对应16进制 12340000456

A = Val(Trim(Text1.Text))
Dim B As String, C As String 'B 存放高位部分 ,C 存放 低位部分

B = Hex(Int(A / &H10000000))
C = Hex(A - (Int(A / &H10000000) * &H10000000))

B = Hex(Int(A / &H10000000))
C = Hex(A - (Int(A / &H10000000) * &H10000000))


' 将 B C 均左 补 0 凑到 7位

Select Case Len(B)
Case 0
B = "0000000"
Case 1
B = "000000" & B
Case 2
B = "00000" & B
Case 3
B = "0000" & B
Case 4
B = "000" & B
Case 5
B = "00" & B
Case 6
B = "0" & B
Case 7
B = B
End Select

Select Case Len(C)
Case 0
C = "0000000"
Case 1
C = "000000" & C
Case 2
C = "00000" & C
Case 3
C = "0000" & C
Case 4
C = "000" & C
Case 5
C = "00" & C
Case 6
C = "0" & C
Case 7
C = C
End Select

Text2.Text = B
Text3.Text = C

'投机取巧的办法一行代码把currency转换为十六进制字符串
cur2hex = Hex(Int(A / &H10000000)) & Hex(A - (Int(A / &H10000000) * &H10000000))

Text4.Text = cur2hex

Text5.Text = B & C & " " & B & " " & C
' Text6.Text = Hex(A)

'如果结果是奇数个字符那么前面要补一个0
If Len(cur2hex) Mod 2 = 1 Then cur2hex = "0" & cur2hex
'然后用0补到16位
cur2hex = Replace(cur2hex & Space(16 - Len(cur2hex)), " ", "0")
Debug.Print cur2hex '打印出来确认一下是否正确
'转换到字节数组
ReDim shuzu(1 To 8)
For i = 1 To 8
shuzu(i) = Val("&H" & Mid(cur2hex, i * 2 - 1, 2))
Next


'*******结果验证********

For i = 1 To 8
Debug.Print i; shuzu(i), Hex(shuzu(i))
Next

脆皮大雪糕 2019-05-08
  • 打赏
  • 举报
回复
其实我再仔细思考了一下,的确你想注释的那两行被我将很多步骤并在了一起,我试着仔细讲一下吧,之所以说试着,是因为这东西在脑袋里面很明确,但是用语言文字表达在我看来有点复杂。 首先,不应该把这两行单独拿出来看,我们要看这一整个函数

'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 。不要学我这么干,我只是偷懒。 至此,你提取出来的那两行解释完毕。
脆皮大雪糕 2019-05-08
  • 打赏
  • 举报
回复
引用 29 楼 eisldkw 的回复:
非常感谢,我来做一下注解,您看我的理解 对不对 Cur2HEX = Right("0" & Hex(curIn - Fix(curIn / 256) * 256), 2) & Cur2HEX curIn = Fix(curIn / 256) 这个算法的来历 比如 &H 12 34 AB CD EF 这个数, &H12 肯定是 低 4字节 上 全加满 即 全为FF FF FF FF 后再加1 加上来的,已经满了 &H12 次 &H FF FF FF FF 而&H 34 AB CD EF 部分 是加了 &H 12 次 &H FF FF FF FF 后 又加的值 同理 &H 34 AB CD EF 说明 这个数中 低3字节 已经加满了 &H34 次 &H FF FF FF 次后 又加了 &H AB CD EF 以此类推
没那么复杂,其实就是十进制转换成其他进制时的标准取余算法 比如要转换成K进制,K就是目标数制的权。那么接下来就是不断的除以这个权值取余数…… 好吧,描述起来比较麻烦,看下面这个链接吧 https://baijiahao.baidu.com/s?id=1621423277747819472&wfr=spider&for=pc 在你的这个需求里面会遇到一个问题,由于你的数值比较大,VB的取余mod计算超过32bit的数据会溢出,整除\计算也会溢出 但是普通除法以及去除小数取整fix运算没问题。所以要用曲线救国的方式进行超过32bit的数值进行取余操作。 其实我的代码下面已经对这段进行了专门的注释。
引用 21 楼 脆皮大雪糕 的回复:
curIn - Fix(curIn / 256) * 256 把商去除小数取整再乘以除数,再拿被除数减一下就是余数了。 由于这个余数小于256,所以hex不会溢出。 又由于hex出来的结果不会自动补0所以 Right("0" & hex(XX) ,2) 把hex的结果在左边补个0,再从右边取2位,当结果为1位的时候前面补的0会一起截出来,如果结果是2位,那么前面的那个0不会有影响。
eisldkw 2019-05-08
  • 打赏
  • 举报
回复
引用 25 楼 脆皮大雪糕 的回复:
不需要搞那么复杂,就是把我两次给的代码合并起来,第二次给的转换函数替换投机取巧的那行。
得了,整理一下,给你一个我认为比较优雅的方式吧
新建窗体,放一个按钮,然后粘贴下面代码试一试。


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





非常感谢,我来做一下注解,您看我的理解 对不对

Cur2HEX = Right("0" & Hex(curIn - Fix(curIn / 256) * 256), 2) & Cur2HEX
curIn = Fix(curIn / 256)

这个算法的来历

比如 &H 12 34 AB CD EF 这个数,
&H12 肯定是 低 4字节 上 全加满 即 全为FF FF FF FF 后再加1 加上来的,已经满了 &H12 次 &H FF FF FF FF
而&H 34 AB CD EF 部分 是加了 &H 12 次 &H FF FF FF FF 后 又加的值
同理 &H 34 AB CD EF 说明 这个数中 低3字节 已经加满了 &H34 次 &H FF FF FF 次后 又加了 &H AB CD EF
以此类推
eisldkw 2019-05-08
  • 打赏
  • 举报
回复
引用 25 楼 脆皮大雪糕 的回复:
不需要搞那么复杂,就是把我两次给的代码合并起来,第二次给的转换函数替换投机取巧的那行。
得了,整理一下,给你一个我认为比较优雅的方式吧
新建窗体,放一个按钮,然后粘贴下面代码试一试。


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





非常感谢,再次膜拜。
eisldkw 2019-05-08
  • 打赏
  • 举报
回复
引用 25 楼 脆皮大雪糕 的回复:
不需要搞那么复杂,就是把我两次给的代码合并起来,第二次给的转换函数替换投机取巧的那行。
得了,整理一下,给你一个我认为比较优雅的方式吧
新建窗体,放一个按钮,然后粘贴下面代码试一试。


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





非常感谢,是我理解有错,谢谢。
舉杯邀明月 2019-05-08
  • 打赏
  • 举报
回复
引用 22 楼 eisldkw 的回复:
[quote=引用 19 楼 舉杯邀明月 的回复:]
[quote=引用 18 楼 eisldkw 的回复:]
[quote=引用 17 楼 舉杯邀明月 的回复:]
[quote=引用 15 楼 eisldkw 的回复:]
. . . . . . . . 

实际上,完全可以选其它数值,关键是要“合理”。
你的“14位10进制数”,转换成“2进制”,基本就是在6字节左右。
 对应的“16进制”,就是大约在“12位16进制”左右了。
把这个“编码值”除以一个合适的系数(必须为 2^n ,n取个“合理”的值),
 可把这“12位左右的16进制”分成“两段”,让它们都不超过&H7FFFFFFF ,
 就可以直接用Hex函数转换和联接了。

不过10楼的代码是有Bug的,有时候转换结果不正确。
比如2019年1月18号之前的编码,可能就错了。
比如: 20190118123456
 10的结果是 0125CED197C0
其实正确值是 125CE0D197C0
你可以用系统的“计算器”转换来看。
这个“补位”应该是在 每个Hex函数结果之后在“高位”补0,
 而不是把两个Hex结果“连接”之后,再去按长度补0
[/quote]

非常感谢,也是大神级的人物。由您的讲解,我感觉 有可能 当 (A - (Int(A / &H10000000) =1时,我们想要的HEX码为 000001 但Hex(A - (Int(A / &H10000000))得到的结果为 1,还会差5个0,不是在开头补一个0 所能解决的。不知道对不对。谢谢。[/quote]

不是差5个,是差6个。
你注意一下,10楼的代码,系数是 &H10000000 ,这后面是“7个0”,
 这样“低段16进制数”就是7位。
而你看成“6位”了 …………

按你在15楼说的,&H10 00 00,则是“5位”,这样“低段”分得太少,
 必然“高段”位数就较多,有“高段”部分出现溢出的风险。

对了,还有一个要注意的,就是这种方法要直接利用Hex函数的结果来拼接,
我在17楼说的 2^n 系数,这个 n值还不能随意选,必须是4的倍数才行。
这种方法,系数值对应的16进制,只能是:&H10、&H100、&H1000……、&H10000000
 这“有限”的7个数。

[/quote]

非常感谢,但我感觉 “ n值还不能随意选,必须是4的倍数才行4的倍数”这个说法好象不对,应该是16的位数,即最小是F所占用的4个BIT位,

以下是我修整后的代码,请帮忙看一下,

. . . . . . . . . . . .

[/quote]
你注意一下: 我说的那个“n”是指数!
我的说法肯定没错,而是你自己的理解错误!!!
2^n ,当n值为“4的倍数”时,(2^n) 的值(这个“表达式”的运算结果),就必然是16的倍数。
脆皮大雪糕 2019-05-07
  • 打赏
  • 举报
回复
还是老老实实写十六进制转换函数吧,不要投机取巧。由于hex、mod都只能处理4字节的整数,currency算的时候会溢出,所以要有一些变通的法子来取余

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不会有影响。
加载更多回复(20)

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧