我知道在Python中读取C double值存在问题。在我的程序中,我正在读取二进制文件并将数值转换为各种大小的整数而没有问题。我使用下面的代码来读取双值。
peakDescriptor["area"] = struct.unpack("d",file.read(8))
价值观与我得到的价值之间存在着巨大的差异。下面的第一个表格是我得到的:
甲烷3.6368230562528605e-307
乙烷-8.243249632731949e + 306
丙烷1.839329701286865e-60
2-甲基丙烷-2.55127317345224e-306
丁烷3.737451552798833e + 59
...
此表显示了值应该是什么:
甲烷97.25
乙烷426.50
丙烷2755.60
2-甲基丙烷3390.25
丁烷10906.60
...
如何正确阅读这些数字?
我的代码可以是found here
如果您在访问文件时遇到问题,请与我们联系!
P.S。我尝试更改格式字符串以包含“>”根据结构文档签名 - 这仍然会导致意外的值,以及一些NaN!
答案 0 :(得分:1)
简短回答:您需要使用正确的字节顺序来解释您的字节。事实证明,在这种情况下,正确的字节顺序既不是小端(订单01234567
)也不是大端(76543210
),而是订单32107654
,所以你需要一个在使用struct
模块之前进行一些预处理。请参阅下面的函数interpret_float
。
更详细:首先查看甲烷值,并且(相当安全)猜测您正在使用的机器是小端,您从文件中读取的字节如下所示:
>>> field = struct.pack('<d', 3.6368230562528605e-307)
>>> field
b'\x00\x00\x003@XP\x00'
正如您已经发现的那样,尝试将这些字节直接解释为IEEE 754二进制64(即双精度)浮点值,假设小端或大端字节顺序不会产生合理的值:< / p>
>>> struct.unpack('<d', field)[0]
3.6368230562528605e-307
>>> struct.unpack('>d', field)[0]
1.08755143765e-312
但是,field
的字节与97.25
的预期值的字节之间存在可疑的相似性。如果将字节扩展为查看其整数值,则稍微容易一些:
>>> list(struct.pack('<d', 97.25))
[0, 0, 0, 0, 0, 80, 88, 64]
>>> list(field)
[0, 0, 0, 51, 64, 88, 80, 0]
不是完美匹配,但0, 80, 88, 64
字节中的97.25
序列看起来与第二个序列中64, 88, 80, 0
的完全相反看起来很可疑。除了little-endian和big-endian之外,还有另外一对IEEE 754双精度浮点数的字节顺序偶尔出现(通常在ARM硬件上),这是字交换的小端,或者是字交换的大端(这两者有时被称为混合端或中端。在您的情况下,看起来您拥有的字节顺序为32107654
,其中7
表示最重要的字节(包含符号位和偏差指数的最高7位的字节) ,和0
最低有效字节(包含分数的8个最低有效位)。因此,如果我们交换这两个词,我们应该能够解释为常规的大端:
>>> def interpret_float(x):
... return struct.unpack('>d', x[4:] + x[:4])
...
>>> interpret_float(field)
(97.25000000000072,)
看起来更有前途!让我们对接下来的两个值进行相同的尝试。你没有给出这些的原始字节,所以我再次需要从你给出的错误值中对它们进行逆向工程。
>>> ethane_field = struct.pack('<d', -8.243249632731949e+306)
>>> interpret_float(ethane_field)
(426.4999999999999,)
>>> propane_field = struct.pack('<d', 1.839329701286865e-60)
>>> interpret_float(propane_field)
(2755.600000000001,)
从这些看来,我们对32107654
的字节顺序的猜测是正确的。
如果我的原始猜测是错误的并且您实际上是在大端机器上,或者您使用的是小端机器,并且您显示的值是通过执行struct.unpack('>d', ...)
而非平原获得的旧的struct.unpack('d', ...)
,然后字节顺序为45670123
,您需要将'>d'
格式替换为interpret_float
,而不是'<d'
。
通过查看Python中的sys.byteorder
,您可以了解主机所使用的字节顺序。在我的机器和任何其他基于x86-64的机器上,它提供'little'
:
>>> import sys
>>> sys.byteorder
'little'