Search code examples
pythonbytepackunpack

combine four bytes and convert to float


I found many other threads on my question, but none quite matched what I wanted, or I had difficulty repurposing.

I am using a function called smbus.read_byte(). according to the doc it returns a long. If I print what it returns, I get a number from 0 to 255.

What I want to do is perform four reads, and then combine that information to generate a float. So 65, 203, 96, 66 should give 25.422.

There were lots of recommendations of using the struct package, but I'm a bit confused about how to combine the results into one number and then convert that to a float.


Solution

  • >>> data = [65, 203, 96, 66]
    >>> b = ''.join(chr(i) for i in data)
    >>> import struct
    >>> struct.unpack('>f', b)
    (25.422000885009766,)
    

    Breaking it down, the join line converts each integer value into a character byte then joins them together into a single string, which is what struct.unpack requires as input. Testing showed that your bytes were in big-endian order, requiring the > in the format to unpack.

    Python 3 makes a distinction between character strings and byte strings, so the join shown above won't work. You can use struct instead of join to combine the values into a byte string, which works in both Python 2 and 3:

    b = struct.pack('4B', *data)
    

    And now that all versions of Python 2 are officially unsupported, perhaps you don't care about backwards compatibility. In Python 3 you can convert a list to bytes directly without having to convert to chr first or use the struct module.

    >>> data = [65, 203, 96, 66]
    >>> b = bytes(data)
    >>> import struct
    >>> struct.unpack('>f', b)
    (25.422000885009766,)