如何检查 Elixir/Erlang 中是否设置了特定位
How to check if a particular bit is set in Elixir/ Erlang
给定任何二进制文件,例如 <<1, 0, 110, 64>>
,我们如何确定是否设置了特定位?
假设我们希望确定 bit-1 和 bit-2 是否已设置,人们会期望这会起作用,但它没有:
<<bit1::bits-size(1), bit2::bits-size(1), _rest::bits>> = <<1, 0, 110, 64>>
给出:
iex(5)> {bit1, bit2}
{<<0::size(1)>>, <<0::size(1)>>}
正确答案(来自 Igor 和其他评论):
<<_::bits-6, bit2::bits-1, bit1::bits-1, num::bits>> = <<1, 0, 110, 64>>
给出了预期的答案:
{bit1,bit2} = {1, 0}
背景
我正在构建一个解析器来处理这个问题:https://msdn.microsoft.com/en-us/library/vs/alm/dd943386(v=office.12).aspx
使用此 C# 代码作为模板我得到了正确的结果:<<1, 0, 110, 64>> = 2.4
我对上面的等效 Elixir 实现按预期工作,但我相信使用位串解析应该是可能的(并且更清晰)
def rk_number(data) do
# IO.puts " ** rk-data: #{inspect data}"
n0 = :binary.decode_unsigned(data, :little)
n1 = n0 >>> 2
n2 =
if (n0 &&& 0x2) == 0x2 do # bit-2, is an int
<<v::little-signed-32>> = <<n1::little-32>>
v
else
n3 = n1 <<< 34
<<v::little-float-64>> = <<n3::little-64>>
v
end
if (n0 &&& 0x1) == 0x1 do # bit-1, div by 100
n2 / 100
else
n2
end
end
这是因为 <<1, 0, 110, 64>>
表示中的每个数字默认大小为 8
。
这就是为什么
<<bit1::bits-size(1), bit2::bits-size(1), _rest::bits>> = <<1, 0, 110, 64>>
{bit1, bit2} = {<<0::size(1)>>, <<0::size(1)>>}
因为 1
of size 8
(00000001
) 的前 2 位等于 0
.
但是
<<bit1::bits-size(8), bit2::bits-size(8), _rest::bits>> = <<1, 0, 110, 64>>
{bit1, bit2} = {<<1>>, <<0>>}
或
<<bit1::bits-size(1), bit2::bits-size(1), _rest::bits>> = <<1::size(1), 0::size(1), 110, 64>>
{bit1, bit2} = {<<1::size(1)>>, <<0::size(1)>>}
如果有一个整数,而你想得到它的前两位,你可以尝试这样的事情:
<<bit1::bits-size(1), bit2::bits-size(1), _rest::bits>> = :binary.encode_unsigned(your_integer)
在考虑了上面的评论之一后,我得到了答案:
<<_::bits-6, bit2::bits-1, bit1::bits-1, num::bits>> = <<1, 0, 110, 64>>
{bit1, bit2} = {1, 0}
给出了预期的结果
给定任何二进制文件,例如 <<1, 0, 110, 64>>
,我们如何确定是否设置了特定位?
假设我们希望确定 bit-1 和 bit-2 是否已设置,人们会期望这会起作用,但它没有:
<<bit1::bits-size(1), bit2::bits-size(1), _rest::bits>> = <<1, 0, 110, 64>>
给出:
iex(5)> {bit1, bit2}
{<<0::size(1)>>, <<0::size(1)>>}
正确答案(来自 Igor 和其他评论):
<<_::bits-6, bit2::bits-1, bit1::bits-1, num::bits>> = <<1, 0, 110, 64>>
给出了预期的答案:
{bit1,bit2} = {1, 0}
背景
我正在构建一个解析器来处理这个问题:https://msdn.microsoft.com/en-us/library/vs/alm/dd943386(v=office.12).aspx
使用此 C# 代码作为模板我得到了正确的结果:<<1, 0, 110, 64>> = 2.4
我对上面的等效 Elixir 实现按预期工作,但我相信使用位串解析应该是可能的(并且更清晰)
def rk_number(data) do
# IO.puts " ** rk-data: #{inspect data}"
n0 = :binary.decode_unsigned(data, :little)
n1 = n0 >>> 2
n2 =
if (n0 &&& 0x2) == 0x2 do # bit-2, is an int
<<v::little-signed-32>> = <<n1::little-32>>
v
else
n3 = n1 <<< 34
<<v::little-float-64>> = <<n3::little-64>>
v
end
if (n0 &&& 0x1) == 0x1 do # bit-1, div by 100
n2 / 100
else
n2
end
end
这是因为 <<1, 0, 110, 64>>
表示中的每个数字默认大小为 8
。
这就是为什么
<<bit1::bits-size(1), bit2::bits-size(1), _rest::bits>> = <<1, 0, 110, 64>>
{bit1, bit2} = {<<0::size(1)>>, <<0::size(1)>>}
因为 1
of size 8
(00000001
) 的前 2 位等于 0
.
但是
<<bit1::bits-size(8), bit2::bits-size(8), _rest::bits>> = <<1, 0, 110, 64>>
{bit1, bit2} = {<<1>>, <<0>>}
或
<<bit1::bits-size(1), bit2::bits-size(1), _rest::bits>> = <<1::size(1), 0::size(1), 110, 64>>
{bit1, bit2} = {<<1::size(1)>>, <<0::size(1)>>}
如果有一个整数,而你想得到它的前两位,你可以尝试这样的事情:
<<bit1::bits-size(1), bit2::bits-size(1), _rest::bits>> = :binary.encode_unsigned(your_integer)
在考虑了上面的评论之一后,我得到了答案:
<<_::bits-6, bit2::bits-1, bit1::bits-1, num::bits>> = <<1, 0, 110, 64>>
{bit1, bit2} = {1, 0}
给出了预期的结果