I have a binary file that I have to parse and I'm using Python. Is there a way to take 4 bytes and convert it to a single precision floating point number?
4 Answers
>>> import struct
>>> struct.pack('f', 3.141592654)
b'\xdb\x0fI@'
>>> struct.unpack('f', b'\xdb\x0fI@')
(3.1415927410125732,)
>>> struct.pack('4f', 1.0, 2.0, 3.0, 4.0)
'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@'
6 Comments
dplass
This only works for 4 or 8 byte floats. What about 10-byte floats?
Startec
I agree with @dplass, what about other floats. And, why is there a comma at the end of this string?
tzot
@startec The question was about 4-byte floats. Which string ends with a comma? Only the tuple from
struct.unpack has a comma.tzot
@PetrKrampl accuracy of C
float (single, 4 bytes) and C double (double, 8 bytes). Python float is really C double. Whatever the accuracy of storing 3.141592654 as a C double, it's lost when it's converted to a C float (by struct.pack) and then back to C double (Python extracts the 4-bytes as a C float and then converts the result back to a C double/Python float). This applies to all implementations of Python that use IEEE754 floating point numbers (CPython does; anyway, I don't know of any non-IEEE754-conformant Python implementation on any system).Gabriel Staples
Note: to view the individual bytes of the bytearray (indicated by b'), use
list(). Ex: list(struct.pack('f', 3.141592654)) returns a list of the individual bytes as [219, 15, 73, 64]. This is very handy. |
Just a little addition, if you want a float number as output from the unpack method instead of a tuple just write
>>> import struct
>>> [x] = struct.unpack('f', b'\xdb\x0fI@')
>>> x
3.1415927410125732
If you have more floats then just write
>>> import struct
>>> [x,y] = struct.unpack('ff', b'\xdb\x0fI@\x0b\x01I4')
>>> x
3.1415927410125732
>>> y
1.8719963179592014e-07
>>>
1 Comment
lifedroid
Alternately you can reference the list position on the RHS
x = struct.unpack('f', b'\xdb\x0fI@')[0]Comment: let's say you are receiving a float variable via MODBUS communication protocol (2 registers, 1 int each), you can convert the message with:
floatvar = struct.unpack('f',int1.to_bytes(2,'big')+int2.to_bytes(2,'big')).
*note MODBUS is big Endian
1 Comment
davnat
pack and unpack by default use the machine’s native format and byte order, but if you need big Endian you can use '>f' format string. See docs.python.org/3/library/…