簡體   English   中英

從二進制文件解壓雙精度值

[英]Unpacking double values from binary file

我了解在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
...

如何正確讀取這些數字?

我的代碼可以在這里找到

原始文件和結果文件在此處此處

如果您在訪問文件時遇到問題,請告訴我!

PS我嘗試按照結構文檔更改格式字符串以包括“>”符號-這仍然會導致意外的值以及許多NaN!

簡短的答案:您需要使用正確的字節順序來解釋您的字節。 事實證明,在這種情況下,正確的字節順序既不是little-endian(順序01234567 )也不是big-endian( 76543210 ),而是32107654的順序,因此在使用struct模塊之前,您需要進行一點點預處理。 請參見下面的函數interpret_float

更詳細地講:首先查看甲烷值,然后(相當安全)猜測您所使用的計算機是低字節序的,從文件中讀取的字節看起來像這樣:

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

正如您已經發現的那樣,嘗試將這些字節直接解釋為IEEE 754二進制64(即雙精度)浮點值,並假定小端或大端字節順序不會產生合理的值:

>>> 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硬件上),這就是單詞交換的little-endian或單詞交換的big-endian(兩者有時都稱為混合字節序或中間字節序)。 在您的情況下,看起來好像您擁有的字節順序為32107654 ,其中7表示最高有效字節(一個包含符號位和偏置指數的最高7位),而0表示最低有效字節(包含分數的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字節順序的32107654是正確的。

如果我最初的猜測是錯誤的,並且您實際上是在大端計算機上,或者您在小端計算機上,則顯示的值是通過執行struct.unpack('>d', ...)而不是普通的舊struct.unpack('d', ...) ,則字節順序為45670123 ,並且您需要用'<d'代替interpret_float'>d'格式。

您可以通過查看Python中的sys.byteorder來找出主機使用的字節順序。 在我的機器上以及在任何其他基於x86-64的機器上,它都給出了'little'字樣:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM