struct on WiPy gives different output than on PC
-
I'm sending serial messages that consist of float values encoded using
struct
between my WiPy and PC (python 2.7). When I encode a decimal value, like 3.4, on the WiPy and then send it to the PC and decode it I get 3.4000000953674316. I noticed that the output ofstruct.pack('<d',3.4)
is slightly different on the WiPy and on the PC.Code on WiPy:
x_wipy= struct.pack('d', 3.4) #encode value print(binascii.hexlify(x_wipy)) #display encoding >>> b'0000004033330b40'
Code on PC (python 2.7):
x_pc = struct.pack('d', 3.4) #encode value print(binascii.hexlify(x_pc)) #display encoding >>> 3333333333330b40
Does anyone know why they differ? Could it be different versions of python?
Other observations:
- WiPy decodes both x_wipy and x_pc correctly to 3.4
- PC decodes x_pc to 3.4 and x_wipy to 3.4000000953674316
- WiPy returns bytes, PC returns str -> this is due to different python versions
-
@alexpul Indeed, but both pack to the same bytes object.
PC:>>> struct.pack("f", 3.4) b'\x9a\x99Y@' >>> struct.unpack("f", b'\x9a\x99Y@') (3.4000000953674316,) >>>
Pycom:
>>> struct.pack("f", 3.4) b'\x9a\x99Y@'
-
Thanks for the great reply @robert-hh!
For any other readers that may be having similar problems: I'm sending the encoded data from the wipy to my PC and I found that even if I encoded it using a single precision float ('f') the value still showed in python as a 64 bit number (hence the really long decimal value). I found that if I forced python to see the number as 32 bit using
numpy.float32(x_wipy)
then the decimal was correctly represented.
-
@alexpul Micropython does supports only 32 bit floats with, giving a ~7 digit precision, and 3.4 being not a binary fraction cannot be encoded w/o precision loss into a float. That is different for numbers, which can be represented as binary fraction, like 3.5. PC Python uses 64 bit floats.
So what you see are rounding errors in different occurences.