# Extracting 15-bit integer values from binary with pattern matching

I have time deltas stored in a file in two formats:
0xxxxxxx
1yyyyyyyyyyyyyyy

In the first format, the time delta is the unsigned 7 bit field represented by xxxxxxx. In the second format, the time delta is the signed 15 bit field represented by yyyyyyyyyyyyyyy

pattern matching to extract the values works for the 7 bit unsigned case:

``````iex(12)> <<0::1, num::size(7)-unsigned-integer-little>> = <<2>>; num
2
``````

But for the intuitive extension to the 15-bit signed case, it isn’t so obvious that it is working correctly:

``````iex(15)> <<1::1, num::size(15)-signed-integer-little>> = <<255,255>>; num
-1
``````

That’s reasonable. However:

``````iex(14)> <<1::1, num::size(15)-signed-integer-little>> = <<254,255>>; num
-3
``````

The value of the 15 bit signed field is -2, not -3.

I’ve been searching for the documentation fruitlessly, so a pointer to the place where I can read the fine documentation, or else just the answer, would be appreciated.

thanks…

http://erlang.org/doc/programming_examples/bit_syntax.html

I have just recently started using bitstrings but I’m trying to debug this with you
In the meantime I link the above docs for you and others.

(I’m no expert in this)

Looks like this goes per 8 bits so:

``````iex(225)> <<_::1, number::15-integer-little-signed>> = <<1::1, 254::8, 127::7>>
<<255, 127>>
iex(226)> number
-2
``````

So: first bit is ignored by you, then 8 bits with 2^7…2^0, then sign::1, then 6 bit 2^13…2^8.
So last chunk is 7 bits with first bit as sign.

Please correct me if I’m wrong, I just figured this out with iex.
Try to debug with this:

``````<<_::1, number::15-integer-little-signed>> = <<1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1>>
``````

Edit:
So just add the ignored bit to the beginning, and reduce the size of the last integer by 1 bit.

``````<<1::1, 255::8, 127::7>>
``````

Thank you for the pointer to the erlang documentation. That looks like the syntax, with the : (erlang) vs. :: (elixir) difference.

Looking at that documentation inspired me to ask what elixir would construct, given the same layout as in the pattern, so I entered the following into iex. It seems that the affected bits are the least significant bits of the first byte and the most significant bits of the second byte.

Without a specification of how to place a 1 bit field and a 15-bit little endian field into two bytes, I can’t say I know how to write the elixir pattern,

I’m going to consider this as closed. (Not sure how to/if I can close a topic in this forum.) Thank you for your insights.

``````iex(57)> Enum.map(-16..16, &(<<0::1, &1::15-signed-little>> <> <<0>> <> <<&1::8>>))
[
<<120, 127, 0, 240>>,
<<120, 255, 0, 241>>,
<<121, 127, 0, 242>>,
<<121, 255, 0, 243>>,
<<122, 127, 0, 244>>,
<<122, 255, 0, 245>>,
<<123, 127, 0, 246>>,
<<123, 255, 0, 247>>,
<<124, 127, 0, 248>>,
<<124, 255, 0, 249>>,
<<125, 127, 0, 250>>,
<<125, 255, 0, 251>>,
<<126, 127, 0, 252>>,
<<126, 255, 0, 253>>,
<<127, 127, 0, 254>>,
<<127, 255, 0, 255>>,
<<0, 0, 0, 0>>,
<<0, 128, 0, 1>>,
<<1, 0, 0, 2>>,
<<1, 128, 0, 3>>,
<<2, 0, 0, 4>>,
<<2, 128, 0, 5>>,
<<3, 0, 0, 6>>,
<<3, 128, 0, 7>>,
<<4, 0, 0, 8>>,
<<4, 128, 0, 9>>,
<<5, 0, 0, 10>>,
<<5, 128, 0, 11>>,
<<6, 0, 0, 12>>,
<<6, 128, 0, 13>>,
<<7, 0, 0, 14>>,
<<7, 128, 0, 15>>,
<<8, 0, 0, 16>>
]
``````
1 Like