Decoding a signed integer

Hi, I am trying to decode hex strings to integers. when I have a positive integer, everything is working and I can use:

Integer.parse(“0292”, 16) == 658

However, when I try to decode a negative integer (aka a signed integer), I am unable to do so. for example:
Integer.parse(“fffffffb”, 16) does not return -5 as I would hope. Is there a way to decode “fffffb” to -5 in elixir?

Here is link to a signed binary converter site. If you type in -5 and click signed and then Dec2Hex, you get “FFFFFFFB”, so I am confident this should be able to work somehow.
http://www.free-test-online.com/binary/signed_converter.html

Not sure if there’s a convenient function somewhere, but you can always convert it to a binary then back:

iex(10)> {x, ""} = Integer.parse("fffffffb", 16)
{4294967291, ""}
iex(11)> <<i :: integer-signed-32>> = <<x :: integer-unsigned-32>>
<<255, 255, 255, 251>>
iex(12)> i
-5
2 Likes

The problem is, that you need a fixed with in bits to be able to express negative numbers in hexadecimal.

In a 32-bit signed environment your 0xFFFFFFFB is -5, but once we increase our size to 64-bit signed, this will be 4294967291.

If though you know that you have to deal with 32-bit signed integers only, then you can do the following:

def convert(str) do
  x = String.to_integer(str)
  <<x :: integer-signed-32>> = <<x :: integer-unsigned-32>>
  x
end

Another idea I do have, which at least should work with most common bit-widths:

Enum.each([8, 16, 32, 64], fn bits ->
  def convert(str, unquote(bits)) do
    x = String.to_integer(str)
    <<x :: integer-signed-unquote(bits)>> = <<x :: integer-unsigned-unquote(bits)>>
    x
  end
end

But in lack of a working elixir environment at hands, this is not tested.

3 Likes

I had to use

    {x, _rest} = Integer.parse(str, 16)
    <<x :: integer-signed-16>> = <<x :: integer-unsigned-16>>
    x

Because it wouldn’t parse "038D".

Maybe this helps someone.

2 Likes