Home > Software design >  How to convert bytes byte by byte to signed int
How to convert bytes byte by byte to signed int

Time:09-21

I have a bytes element. My word size is 1, a single byte. The contents can be b'\xff\xff\x01' 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'\xff\xff\x01']

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.

CodePudding user response:

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'\xff\xff\x01']

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'\xff\xff\x01']

CodePudding user response:

Another way, using Numpy:

>>> import numpy as np
>>> np.frombuffer(b'\xff\xff\x01', dtype=np.int8)
array([-1, -1,  1], dtype=int8)

CodePudding user response:

This solution is idiotic but at least it works.

data = b'\xff\xff\x01'
result = list(struct.unpack('b' * len(data), data))
  • Related