对于第一个操作,我假设您只想保留整数中设置的字节数,因此您可以这样做:
julia> a = 1026
1026
julia> [(a>>((i-1)<<3))%UInt8 for i in 1:sizeof(a)-leading_zeros(a)>>3]
2-element Vector{UInt8}:
0x02
0x04
解释:
-
leading_zeros(a) 获取以a 开头的零位数
-
leading_zeros(a)>>3 计算完全空的字节数(>>3 将数字右移3 位;在这种情况下,地板除以 8)
-
sizeof(a)-leading_zeros(a)>>3 计算要转换的字节数
-
(i-1)<<3) 计算我们需要移动索引的位数(在本例中为 i-1 乘以 8)
-
(a>>((i-1)<<3))%UInt8 获取a 的i-1th 字节
对于第二个操作,我假设如果您有奇数个字符,我们会用 0 位 + 填充最后一个字节的剩余部分,我们不需要检查传递的数据是否有效:
julia> a = "ABCDEF12345678"
"ABCDEF12345678"
julia> function s2b(a::String)
b = zeros(UInt8, (sizeof(a) + 1) >> 1)
for (i, c) in enumerate(codeunits(a))
b[(i+1)>>1] |= (c - (c < 0x40 ? 0x30 : 0x37))<<(isodd(i)<<2)
end
return b
end
s2b (generic function with 1 method)
julia> s2b(a)
7-element Vector{UInt8}:
0xab
0xcd
0xef
0x12
0x34
0x56
0x78
这两种方法都应该很快,但很难保证它们是最快的。
编辑
基准测试:
julia> function f1(a)
aHexStr = string(a,base = 16,pad = 4) #2 bytes, 4 chars
b = zeros(UInt8,2)
k = 1
for i in 1:2:4
b[k] = parse(UInt8,aHexStr[i:i+1],base = 16)
k += 1
end
return b
end
f1 (generic function with 1 method)
julia> f2(a) = [(a>>((i-1)<<3))%UInt8 for i in 1:sizeof(a)-leading_zeros(a)>>3]
f2 (generic function with 1 method)
julia> using BenchmarkTools
julia> a = 1026
1026
julia> @btime f1($a)
141.795 ns (5 allocations: 224 bytes)
2-element Vector{UInt8}:
0x04
0x02
julia> @btime f2($a)
29.317 ns (1 allocation: 64 bytes)
2-element Vector{UInt8}:
0x02
0x04
julia> function s2b(a::String)
b = zeros(UInt8, (sizeof(a) + 1) >> 1)
for (i, c) in enumerate(codeunits(a))
b[(i+1)>>1] |= (c - (c < 0x40 ? 0x30 : 0x37))<<(isodd(i)<<2)
end
return b
end
s2b (generic function with 1 method)
julia> a = "ABCDEF12345678"
"ABCDEF12345678"
julia> @btime hex2bytes($a)
50.000 ns (1 allocation: 64 bytes)
7-element Vector{UInt8}:
0xab
0xcd
0xef
0x12
0x34
0x56
0x78
julia> @btime s2b($a)
48.830 ns (1 allocation: 64 bytes)
7-element Vector{UInt8}:
0xab
0xcd
0xef
0x12
0x34
0x56
0x78
正如@SundarR 在后一种情况下评论的那样,应该使用hex2bytes。我忘记了它的存在。