我试图找出如何读取历史二进制数据文件。我相信它来自一个较旧的32位Solaris系统。我正在查看文件中我认为包含32位浮点数(不是IEEE浮点数)的部分。格式似乎是(作为十六进制转储):
xx41 xxxx
xx42 xxxx
这些位置的41和42在浮点数上始终如一。我担心我没有任何其他信息可以添加到此。所以我的问题的第一部分是,这是什么格式?如果第一部分无法直接回答,那么可能的可能性列表就会很棒。最后,您如何建议确定这是什么格式?感谢您的投入。
答案 0 :(得分:4)
这可能是PDP-11格式吗?对我来说,赠品是第二个字节大部分是常量,这表明浮点格式的指数最终在第二个字节而不是第一个字节(正如你所期望的那样) big-endian机器)或最后一台(用于小端机器)。 PDP-11因浮动和整数的有趣字节顺序而臭名昭着;查看此Floating-Point Formats页面底部附近的资料。
41
和42
的值似乎与大致单位幅度的正值一致:PDP-11格式的指数偏差似乎为128
,因此对于不寻常的字节顺序,我希望你列出的第二个字节包含符号和指数的最高7位;这将使41
的第二个字节的无偏指数为2或3,具体取决于第8个指数位(应该显示为第一个字节的MSB)。
有关PDP-11格式的简要说明,另请参阅this page。
[编辑]以下是一些Python代码,用于将您描述的形式的4字节字符串转换为Python float,假设4字节字符串表示PDP-11格式的浮点数。
import struct
def pdp_to_float(xs):
"""Convert a 4-byte PDP-11 single-precision float to a Python float."""
ordered_bytes = ''.join(xs[i] for i in [1, 0, 3, 2])
n = struct.unpack('>I', ordered_bytes)[0]
fraction = n & 0x007fffff
exponent = (n & 0x7f800000) >> 23
sign = (n & 0x80000000) >> 31
hidden = 1 if exponent != 0 else 0
return (-1)**sign * 2**(exponent-128) * (hidden + fraction / 2.0**23)
示例:
>>> pdp_to_float('\x00\x00\x00\x00')
0.0
>>> pdp_to_float('\x23\x41\x01\x00')
5.093750476837158
>>> pdp_to_float('\x00\x42\x00\x00')
16.0
答案 1 :(得分:3)
所描述的数据与通常的IEEE 754格式一致,以big-endian顺序存储,然后由little-endian转储程序一次显示两个字节。
区间[8,128]中的32位浮点数具有0x41或0x42的第一个字节。考虑这样一个数字,也许是0x41010203。首先存储大端,它将在内存中显示为四个字节0x41,0x01,0x02和0x03。当转储程序读取16字节整数时,小端优先,它将读取并显示0x0141和0x0302。