How to convert bytes byte by byte to signed int

Question:

I have a bytes element. My word size is 1, a single byte. The contents can be b'xffxffx01' meaning [-1, -1, 1].

I want to convert it to the int representation from the bytes form.
Logically my attempt is:

ints = [int.from_bytes(j, byteorder='little', signed=True) for j in b'xffxffx01']

TypeError: cannot convert ‘int’ object to bytes

However this does not work as the for j in bytes() converts a bytes element directly into an int j. This is however an unsigned conversion, I need signed. How do I convert my bytes, byte by byte, into a signed integer.

Asked By: Tarick Welling

||

Answers:

This solution is idiotic but at least it works.

data = b'xffxffx01'
result = list(struct.unpack('b' * len(data), data))
Answered By: Tarick Welling

However this does not work as the for j in bytes() converts a bytes element directly into an int j.

As you’ve noticed, the bytes is already an iterable over integer values. If we have a lot of data, it would be more memory efficient to keep the bytes as is, and convert values on demand. We can simply do the math to convert the unsigned interpretation of a byte to the corresponding signed representation:

def signed_byte(b):
    return b - 256 if b >= 128 else b

And wrap the indexing process:

def get_signed(data, index):
    return signed_byte(data[index])

If we want or need to do all the conversion ahead of time, that feeds directly into the list comprehension:

ints = [signed_byte(b) for b in b'xffxffx01']

On the other hand, we can reframe the question: to get a bytes object from the original data as a subsequence (like how it worked in 2.x), we can use a 1-element slice instead; or we can wrap the int value into a new bytes. The former will be tricky to adapt to the original code, but the latter is trivial:

ints = [int.from_bytes(bytes([b]), byteorder='little', signed=True) for b in b'xffxffx01']
Answered By: Karl Knechtel

Another way, using Numpy:

>>> import numpy as np
>>> np.frombuffer(b'xffxffx01', dtype=np.int8)
array([-1, -1,  1], dtype=int8)
Answered By: Karl Knechtel

I don’t know if it still helps! I saw your comment just now 🙂

ints = [int.from_bytes(bytes([j]), byteorder='little', signed=True) for j in b'xffxffx01']
Answered By: realSamy
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.