如何解码包含浮点数组的二进制文件?
encoded_floats_hex = [ "35F1AC3D", "610BB63D", "8C25BF3D", "B73FC83D", "E259D13D", "0E74DA3D", "B5AB5C00", "D3972400", "6D9B2400", "B5A82400", "4A75E003", "ED20E403", "11D7F803", "0F7EEF03", "BAD41500", "56341200", "6B5C1200", "BE753200", "E94B3E00", "EA4D3600", "BE372E00", "6BDC1500", "56FC1200", "B9D41300", "E9CC7200", "D6347E00", "BB547600", "6E7C6E00", "5A541600", "B94B1200", "EECD1300", "DBD73200", "B7FD3D00", "6ADC3600", "59342E00", "B64C1600", "EA541200", "DF741200", "9281F000", "FC39F600", "5B0EFC00", "3254F600", "FB7B0B00", "EDEE0E00", "D71D0900", "3D2A1900", "2C261900", "573A1B00", "7D2A1700", "6B1E0B00", "55EA0E00", "3C660900", "2BE63900", "D56B3900", "FF1E3B00", "D52D3700", "D43A0B00", "3F260F00", "552A0900", "6B1A1900", "7D6E1900", "54FA1A00", "2C661700", "3DE60B00", "D71B0F00", "ED2E0900", "FB3D7900", "D42A7900", "2D267900", "3B1A7700", "55EA0B00", "6F7E0F00", "74EA0A00", "55661900", "2F261900", "352A1900", "DB3E1700", "EC2D0B00", "F51A0F00", "DBE70A00", "2D6A3900", "37FA3900", "5C6E3900", "6C1A3700", "77260B00", "5D260F00", "2B3A0B00", "352E1900", "DC1D1900", "EB6A1900", "F5E71600", "DF7A0B00", "35EA0F00", "341E0B00" ]
这个数组里包含的是小端格式的浮点数的十六进制值,每个浮点数占4个字节。前6个值可以解码,但之后的解码结果却很奇怪:
# Convert the hex strings to bytes
encoded_bytes = [bytes.fromhex(x) for x in encoded_hex]
# convert the each byte array into a float
float_values = [struct.unpack('f', x)[0] for x in encoded_bytes]
float_values
[0.08444444090127945,
0.08888889104127884,
0.09333333373069763,
0.09777777642011642,
0.10222221910953522,
0.1066666692495346,
8.510462523131517e-39,
3.360542129100596e-39,
3.361834126284704e-39,
3.366598541063408e-39,
1.3192464977331103e-36,...]
看起来这些值是用某种自定义的增量编码方式编码的。
另一方面,整个数组的值都是在0到1之间的数字,不需要用科学计数法表示,并且除了最后几个值外,都是从0.0逐渐增加到1.0。
有没有什么方法可以解码这些值呢?
我尝试了几种解码方式,但都没有得到预期的结果。
1 个回答
浮点数的16进制值占4个字节,采用小端格式
我们先关注这一部分。
文件的读取其实很简单,所以我们假设它已经被读取到内存中,变成了一串这样的16进制字符串。
因为你的数据是小端格式,所以可以通过反转bytes.fromhex的结果来解码这些字节:
bytes.fromhex("35F1AC3D")[::-1]
接下来,我们只需要把这些字节转换成目标格式的数据(比如这里是浮点数,因为你的字符串只有4个字节):
float_out = struct.unpack('>f', bytes.fromhex("35F1AC3D")[::-1])[0]
另外,直接使用'<f'格式(小端)而不反转字节也是可以的:
float_out = struct.unpack('<f', bytes.fromhex("35F1AC3D"))[0]
只需对每个元素进行这个操作,完成了。
根据@Marek Piotrowski的建议,下面有更多信息来自这里:
对于'f'、'd'和'e'这些转换代码,打包后的表示使用的是IEEE 754的binary32、binary64或binary16格式(分别对应'f'、'd'或'e'),与平台使用的浮点格式无关。