2011-08-19 44 views
10

我正在讀的二進制文件在python這樣的:蟒:解包IBM 32位浮點

from struct import unpack 

ns = 1000 
f = open("binary_file", 'rb') 

while True: 
    data = f.read(ns * 4) 
    if data == '': 
     break 
    unpacked = unpack(">%sf" % ns, data) 
    print str(unpacked) 

當我意識到unpack(">f", str)爲拆包IEEE浮點,我的數據是IBM的32位浮點號碼

我的問題是: 如何促使我的unpack解壓縮IBM 32位浮點型數字?

我不介意使用像​​來擴展python以獲得更好的性能。

編輯:我做了一些搜索: http://mail.scipy.org/pipermail/scipy-user/2009-January/019392.html

這看起來非常有前途,但我希望得到更有效:有潛在的數以萬計的循環。

編輯:張貼答案下面。謝謝你的提示。

+7

見http://mail.scipy.org/pipermail/scipy-user/2009-January/019392.html – NPE

+0

@aix,任何排列順序問題要注意的? –

+1

請重新發布該編輯作爲答案,並在兩天後接受它。不要爲你的問題添加答案。 – agf

回答

3

我想我的理解是: 首先解包串符號的4位整數,然後使用此功能:

def ibm2ieee(ibm): 
    """ 
    Converts an IBM floating point number into IEEE format. 
    :param: ibm - 32 bit unsigned integer: unpack('>L', f.read(4)) 
    """ 
    if ibm == 0: 
     return 0.0 
    sign = ibm >> 31 & 0x01 
    exponent = ibm >> 24 & 0x7f 
    mantissa = (ibm & 0x00ffffff)/float(pow(2, 24)) 
    return (1 - 2 * sign) * mantissa * pow(16, exponent - 64) 

感謝所有誰幫助!

IBM浮點架構,如何編碼和解碼: http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture

我的解決辦法: 我寫了一個類,我想用這種方式,它可以是一個有點快,因爲使用Struct對象,所以解壓fmt只編譯一次。編輯:也是因爲它一次解包大小*字節,而拆包可能是一個昂貴的操作。

from struct import Struct 

class StructIBM32(object): 
    """ 
    see example in: 
    http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture#An_Example 

    >>> import struct 
    >>> c = StructIBM32(1) 
    >>> bit = '11000010011101101010000000000000' 
    >>> c.unpack(struct.pack('>L', int(bit, 2))) 
    [-118.625] 
    """ 
    def __init__(self, size): 
     self.p24 = float(pow(2, 24)) 
     self.unpack32int = Struct(">%sL" % size).unpack 
    def unpack(self, data): 
     int32 = self.unpack32int(data) 
     return [self.ibm2ieee(i) for i in int32] 
    def ibm2ieee(self, int32): 
     if int32 == 0: 
      return 0.0 
     sign = int32 >> 31 & 0x01 
     exponent = int32 >> 24 & 0x7f 
     mantissa = (int32 & 0x00ffffff)/self.p24 
     return (1 - 2 * sign) * mantissa * pow(16, exponent - 64) 

if __name__ == "__main__": 
    import doctest 
    doctest.testmod() 
+1

你可能會從封裝邏輯中失去更多的時間,否則你會獲得更多的時間。在提出表演申請前,你應該進行基準測試 – zwol

相關問題