IBM floating point 32-bit numbers cannot be parsed directly in python, you need to unpack it by yourself. The format is described here:
1 7 24 width in bits
+-+-------+------------------------+
|S| Exp | Fraction |
+-+-------+------------------------+
31 30 24 23 0 bit index (0 on right)
bias +64
So what we need to do is unpack the byte stream to unsigned 32 bit integer, and calculate each part of the above format. We'll use the example in http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture#An_Example
In the example the nibbles look like this:
1 7 24 width in bits
+-+-------+------------------------+
|S| Exp | Fraction |
|1|1000010|011101101010000000000000|
+-+-------+------------------------+
31 30 24 23 0 bit index (0 on right)
bias +64
Expected output is -118.625
>>> import struct >>> bit = '11000010011101101010000000000000' >>> n = int(bit, 2) # convert bit string to integer >>> sign = n >> 31 & 0x01 >>> sign = 1 - sign * 2 # 1 negative, 0 positive >>> exponent = n >> 24 & 0x7f >>> exponent = pow(16, exponent - 64) # exponents are power of 16 not 2, and bias is 64 >>> mantissa = n & 0x00ffffff # bit representation of fraction part in the above graph >>> mantissa = float(mantissa) / pow(2, 24) # convert fraction(mantissa) part to its real value >>> sign * exponent * mantissa -118.625
So everything in a function:
def ibm2ieee(ibm):
"""
Converts an IBM floating point number into IEEE format.
:param: ibm - 32 bit unsigned integer: unpack('>L', f.read(4))
"""
sign = ibm >> 31 & 0x01
exponent = ibm >> 24 & 0x7f
mantissa = ibm & 0x00ffffff
mantissa = (mantissa * 1.0) / pow(2, 24)
ieee = (1 - 2 * sign) * mantissa * pow(16, exponent - 64)
return ieee
I also have a post in stackoverflow.com that implemented a class to unpack IBM 32-bit float: http://stackoverflow.com/questions/7125890/python-unpack-ibm-32-bit-float-point
Reference:
[1]http://mail.scipy.org/pipermail/scipy-user/2009-January/019392.html
[2]http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture
No comments:
Post a Comment