从二进制fi解包双精度值

2024-04-26 11:23:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道在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

原始文件和结果文件是herehere

请让我知道如果你有问题访问文件!在

另外,我已经根据struct文档尝试更改格式化字符串以包含“>;”符号-这仍然会导致意外的值,以及许多NaN!在


Tags: 文件代码程序here二进制精度area整数
1条回答
网友
1楼 · 发布于 2024-04-26 11:23:49

简而言之:你需要用正确的字节顺序来解释你的字节。在本例中,正确的字节顺序既不是little-endian(order01234567)也不是big-endian(76543210),而是顺序32107654,因此在使用struct模块之前,您需要一点预处理。请参阅下面的函数interpret_float。在

更详细地说:首先看甲烷值,然后让(相当安全的)猜测您使用的机器是little endian,您从文件中读取的字节如下所示:

>>> field = struct.pack('<d', 3.6368230562528605e-307)
>>> field
b'\x00\x00\x003@XP\x00'

正如您已经发现的,尝试将这些字节直接解释为IEEE 754二进制64(即,双精度)浮点值,假设小端字节顺序或大端字节顺序都不会产生合理的值:

^{pr2}$

但是,field的字节和期望值{}的字节之间存在可疑的相似性。如果将字节展开以查看其整数值,则更容易看到:

>>> list(struct.pack('<d', 97.25))
[0, 0, 0, 0, 0, 80, 88, 64]
>>> list(field)
[0, 0, 0, 51, 64, 88, 80, 0]

这不是一个完美的匹配,但是97.25字节中的0, 80, 88, 64序列与第二个序列{}完全相反。除了little-endian和big-endian之外,ieee754双精度浮点还有另一对字节顺序偶尔出现(通常在ARM硬件上),那就是字交换的小尾数(word-swapped-little-endian)或字交换的大端(这两者有时被称为混合端或中端)。在您的例子中,看起来好像您拥有的字节是按32107654的顺序排列的,其中7表示最高有效字节(包含符号位和有偏指数的最高有效位7位),而{}是最低有效字节(包含分数的8个最低有效位)。因此,如果我们交换这两个词,我们应该可以将其解释为常规的big-endian:

>>> 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字节顺序的猜测是正确的。在

如果我最初的猜测是错误的,而您实际上是在一个大的endian机器上,或者您在一个小endian机器上,并且您显示的值是通过执行struct.unpack('>d', ...)而不是普通的struct.unpack('d', ...)来获得的,那么字节顺序是45670123,您需要将interpret_float中的'>d'格式替换为{}。在

通过查看Python中的sys.byteorder,可以了解主机使用的字节顺序。在我的机器上,以及任何其他基于x86-64的机器上,它给出'little'

>>> import sys
>>> sys.byteorder
'little'

相关问题 更多 >