K.Mulier K.Mulier - 6 months ago 19
Python Question

Python outputs strange bytearray

Python sometimes generates strange cryptic byte arrays. I have no clue how to interpret them.

Consider the following example.

import struct
floats = [3.14, 2.7, 0.0, -1.0, 1.1]
s = struct.pack('f'*len(floats), *floats)
print("The bytes:")
print(s)


The struct.pack function should output the 'bytes-representation' of each value in the list. The list consists of 64-bit floating point numbers (my computer is 64-bit), so I would expect every float to be represented by 8 bytes:

3.14 -> 0x40 0x09 0x1E 0xB8 0x51 0xEB 0x85 0x1F
2.7 -> 0x40 0x05 0x99 0x99 0x99 0x99 0x99 0x9A
0.0 -> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-1.0 -> 0xBF 0xF0 0x00 0x00 0x00 0x00 0x00 0x00
1.1 -> 0x3F 0xF1 0x99 0x99 0x99 0x99 0x99 0x9A


By the way, I have used the following website to make the proper conversion: http://babbage.cs.qc.cuny.edu/IEEE-754.old/Decimal.html

Unfortunately, Python does not output those bytes I would expect. Instead, Python outputs some very cryptic list of bytes. But is this really a list of bytes? The thing that Python outputs is so strange:

b'\xc3\xf5H@\xcd\xcc,@\x00\x00\x00\x00\x00\x00\x80\xbf\xcd\xcc\x8c?'


Please help me to understand what Python is doing here.

Answer

You want to unpack as double but in the program you use the specifier for float: f. So that's what you get:

c3 f5 48 40 for 3.14

(See python struct pack double for why you see some ASCII characters.)

This code will print out one line of hex per number:

import struct
floats = [3.14, 2.7, 0.0, -1.0, 1.1]
s = []
for f in floats:
    s.append(struct.pack('d', f))
print("The bytes:")
for floatInHex in s:
  for byteval in floatInHex:
    print ('%02x' % byteval, end=""),
  print ()

Result:

The bytes:
1f85eb51b81e0940
9a99999999990540
0000000000000000
000000000000f0bf
9a9999999999f13f