2011-08-19 6 views
10

मैं इस तरह अजगर में एक बाइनरी फ़ाइल पढ़ रहा था:अजगर: खोल आईबीएम 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) आईईईई चल बिन्दु खोल के लिए है, अपने डेटा आईबीएम 32-बिट नाव बिंदु है संख्या

मेरा प्रश्न है: आईबीएम 32-बिट फ्लोट पॉइंट प्रकार संख्याओं को अनपैक करने के लिए मैं अपने unpack को कैसे लागू कर सकता हूं?

मुझे बेहतर प्रदर्शन प्राप्त करने के लिए पायथन का विस्तार करने के लिए ctypes जैसे उपयोग करने में कोई फर्क नहीं पड़ता।

संपादित करें: मैं कुछ खोज किया: 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, किसी भी endianness मुद्दों के बारे में पता होना करने के लिए? –

+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) 

सब जो मदद के लिए धन्यवाद!

आईबीएम फ्लोटिंग प्वाइंट आर्किटेक्चर, कैसे सांकेतिक शब्दों में बदलना और डिकोड करने के लिए: http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture

मेरे समाधान: मैं क्योंकि Struct वस्तु का इस्तेमाल किया एक वर्ग ने लिखा है, मैं इस तरह से लगता है, यह थोड़ा तेजी से हो सकता है,, ताकि अनपैक एफएमटी केवल एक बार संकलित हो। संपादित करें: यह भी क्योंकि यह एक बार में अनपॅकिंग आकार * बाइट्स है, और अनपॅकिंग एक महंगा ऑपरेशन हो सकता है।

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