python: unpack IBM 32-bit float point

匿名 (未验证) 提交于 2019-12-03 01:38:01

问题:

I was reading a binary file in python like this:

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) 

when I realized unpack(">f", str) is for unpacking IEEE floating point, my data is IBM 32-bit float point numbers

My question is: How can I impliment my unpack to unpack IBM 32-bit float point type numbers?

I don't mind using like ctypes to extend python to get better performance.

EDIT: I did some searching: http://mail.scipy.org/pipermail/scipy-user/2009-January/019392.html

This looks very promising, but I want to get more efficient: there are potential tens of thousands of loops.

EDIT: posted answer below. Thanks for the tip.

回答1:

I think I understood it: first unpack the string to unsigned 4 byte integer, and then use this function:

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) 

Thanks for all who helped!

IBM Floating Point Architecture, how to encode and decode: http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture

My solution: I wrote a class, I think in this way, it can be a bit faster, because used Struct object, so that the unpack fmt is compiled only once. EDIT: also because it's unpacking size*bytes all at once, and unpacking can be an expensive operation.

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!