1 Jan 2012

python: unpack IBM 32-bit float point

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: