5

I am faced with a problem in Python and I think I don't understand how signed numbers are handled in Python. My logic works in Java where everything is signed so need some help in Python.

I have some bytes that are coded in HEX and I need to decode them and interpret them to numbers. The protocol are defined.

Say the input may look like:
raw = '016402570389FFCF008F1205DB2206CA' And I decode like this:

bin_bytes = binascii.a2b_hex(raw)
lsb = bin_bytes[5] & 0xff
msb = bin_bytes[6] << 8
aNumber = int(lsb | msb)
print("     X: " + str(aNumber / 4000.0))

After dividing by 4000.0, X can be in a range of -0.000025 to +0.25.

This logic works when X is in positive range. When X is expected to be negative, I am getting back a positive number. I think I am not handling "msb" correctly when it is a signed number. How should I handlehandle negative signed number in Python?

Any tips much appreciated.

Vince Yau
  • 515
  • 1
  • 5
  • 16
  • You can use the [struct module](https://docs.python.org/3.6/library/struct.html) to do this: with unpack function. – Fady Saad Sep 21 '17 at 23:09
  • 2
    Possible duplicate of [Convert variable-sized byte array to a integer/long](https://stackoverflow.com/questions/25259947/convert-variable-sized-byte-array-to-a-integer-long) – anthony sottile Sep 22 '17 at 00:07
  • also perhaps https://stackoverflow.com/questions/1887506/convert-python-byte-to-unsigned-8-bit-integer – anthony sottile Sep 22 '17 at 00:08

1 Answers1

6

You can use Python's struct module to convert the byte string to integers. It takes care of endianness and sign extension for you. I guess you are trying to interpret this 16-byte string as 8 2-byte signed integers, in big-endian byte order. The format string for this is '>8h. The > character tells Python to interpret the string as big endian, 8 means 8 of the following data type, and h means signed short integers.

import struct
nums = struct.unpack('>8h', bin_bytes)

Now nums is a tuple of integers that you can process further.

I'm not quite sure if your data is little or big endian. If it is little-endian, you can use < to indicate that in the struct.unpack format string.

mtrw
  • 34,200
  • 7
  • 63
  • 71