在位掩码中找到一个的位置 - Julia
Finding the location of ones in a bit mask - Julia
我有一系列值,每个值都存储为 UInt16
。这些数字中的每一个都代表一个位掩码 - 这些数字是已发送到微处理器的命令,告诉它哪些引脚设置为高电平或低电平。我想解析这个命令箭头,以找出每次都将哪些引脚设置为高电平,以便以后更容易分析。
考虑示例值 0x3c00
,十进制为 15360
,二进制为 0011110000000000
。目前我有以下功能
function read_message(hex_rep)
return findall.(x -> x .== '1',bitstring(hex_rep))
end
UInt16
数组的每个元素都会调用它。有没有 better/more 有效的方法来做到这一点?
我可以建议将您的矢量填充到 Vector{UInt64}
中,然后使用它来手动构建 BitVector
。以下应该主要工作(即使对于 UInt16
以外的输入元素类型),但我没有考虑您可能想要尊重的特定字节顺序:
julia> function read_messages(msgs)
bytes = reinterpret(UInt8, msgs)
N = length(bytes)
nchunks, remaining = divrem(N, sizeof(UInt64))
padded_bytes = zeros(UInt8, sizeof(UInt64) * cld(N, sizeof(UInt64)))
copyto!(padded_bytes, bytes)
b = BitVector(undef, N * 8)
b.chunks = reinterpret(UInt64, padded_bytes)
return b
end
read_messages (generic function with 1 method)
julia> msgs
2-element Vector{UInt16}:
0x3c00
0x8000
julia> read_messages(msgs)
32-element BitVector:
0
0
0
0
0
0
0
0
0
⋮
0
0
0
0
0
0
0
1
julia> read_messages(msgs) |> findall
5-element Vector{Int64}:
11
12
13
14
32
julia> bitstring.(msgs)
2-element Vector{String}:
"0011110000000000"
"1000000000000000"
(摆脱不必要的 undef
位向量分配需要一些黑魔法,我相信。)
最佳方法可能取决于您希望如何处理十六进制值向量。但是这里有一种处理单个十六进制的方法,它比 OP 中的方法快得多:
function readmsg(x::UInt16)
N = count_ones(x)
inds = Vector{Int}(undef, N)
if N == 0
return inds
end
k = trailing_zeros(x)
x >>= k + 1
i = N - 1
inds[N] = n = 16 - k
while i >= 1
(x, r) = divrem(x, 0x2)
n -= 1
if r == 1
inds[i] = n
i -= 1
end
end
return inds
end
我有一系列值,每个值都存储为 UInt16
。这些数字中的每一个都代表一个位掩码 - 这些数字是已发送到微处理器的命令,告诉它哪些引脚设置为高电平或低电平。我想解析这个命令箭头,以找出每次都将哪些引脚设置为高电平,以便以后更容易分析。
考虑示例值 0x3c00
,十进制为 15360
,二进制为 0011110000000000
。目前我有以下功能
function read_message(hex_rep)
return findall.(x -> x .== '1',bitstring(hex_rep))
end
UInt16
数组的每个元素都会调用它。有没有 better/more 有效的方法来做到这一点?
我可以建议将您的矢量填充到 Vector{UInt64}
中,然后使用它来手动构建 BitVector
。以下应该主要工作(即使对于 UInt16
以外的输入元素类型),但我没有考虑您可能想要尊重的特定字节顺序:
julia> function read_messages(msgs)
bytes = reinterpret(UInt8, msgs)
N = length(bytes)
nchunks, remaining = divrem(N, sizeof(UInt64))
padded_bytes = zeros(UInt8, sizeof(UInt64) * cld(N, sizeof(UInt64)))
copyto!(padded_bytes, bytes)
b = BitVector(undef, N * 8)
b.chunks = reinterpret(UInt64, padded_bytes)
return b
end
read_messages (generic function with 1 method)
julia> msgs
2-element Vector{UInt16}:
0x3c00
0x8000
julia> read_messages(msgs)
32-element BitVector:
0
0
0
0
0
0
0
0
0
⋮
0
0
0
0
0
0
0
1
julia> read_messages(msgs) |> findall
5-element Vector{Int64}:
11
12
13
14
32
julia> bitstring.(msgs)
2-element Vector{String}:
"0011110000000000"
"1000000000000000"
(摆脱不必要的 undef
位向量分配需要一些黑魔法,我相信。)
最佳方法可能取决于您希望如何处理十六进制值向量。但是这里有一种处理单个十六进制的方法,它比 OP 中的方法快得多:
function readmsg(x::UInt16)
N = count_ones(x)
inds = Vector{Int}(undef, N)
if N == 0
return inds
end
k = trailing_zeros(x)
x >>= k + 1
i = N - 1
inds[N] = n = 16 - k
while i >= 1
(x, r) = divrem(x, 0x2)
n -= 1
if r == 1
inds[i] = n
i -= 1
end
end
return inds
end