Converting from Microsoft Binary Format floats to Python Float

Discussion in 'Python' started by geskerrett@hotmail.com, Aug 26, 2005.

  1. Guest

    In the '80's, Microsoft had a proprietary binary structure to handle
    floating point numbers, In a previous thread, Bengt Richter posted
    some example code in how to convert these to python floats;

    http://groups.google.com/group/comp...ccc20a1d8d5/4aadc71be8aeddbe#4aadc71be8aeddbe

    I copied this code and modified it slightly, however, you will notice
    that for one of the examples, the conversion isn't exact.

    Can anyone advise me on how to modify this code to correct for this
    situation ?
    I think the problem may be related to the different lengths of the
    mantissa. For double precision (8bytes) MBF format had 55 where as
    Python floats (IEEE) has only 52 ??

    Sample Code Below ----------------------
    # Conversion of Microsoft Binary Format numbers to Python Floats

    import binascii as bn
    import struct as st


    data = [(1234567890,'000000AF052C139F­'),
    (4069954144,'00000060929672A0'­),
    (999999.99, '703D0AD7FF237494'),
    ( 88888.88, '400ad7a3709c2d91'),
    ( 22222.22, '400ad7a3709c2d8f'),
    ( 33333.33, 'b047e17a54350290'),
    ( 1500.34, '7814ae47e18a3b8b'),
    ( 42345.00, '0000000000692590'),
    ]


    def msd2float(bytes):
    #take out values that don't make sense possibly the NaN and
    Infinity ??
    if sum(bytes) in [0,72,127]:
    return 0.0
    b = bytes[:]
    sign = bytes[-2]&0x80
    b[-2] |= 0x80 #hidden most sig bit in place of sign
    exp = bytes[-1] - 0x80 - 56 #exponent offset
    acc = 0L
    for i,byte in enumerate(b[:-1]):
    acc |=(long(byte)<<(i*8))
    return (float(acc)*2.0**exp)*((1.,-1.­)[sign!=0])

    for line in data:
    inval = line[0]
    binval = bn.unhexlify(line[1])
    le_bytes = list(st.unpack('BBBBBBBB',binv­al))
    outval = msd2float(le_bytes)
    print " In:",inval, "\nOut:",outval,"\n"

    Sample Output ------------------------
    C:/Python24/pythonw.exe -u "C:/pytest/dms/Test MBF.pyw"
    In: 1234567890
    Out: 1234567895.5

    In: 4069954144
    Out: 4069954144.0

    In: 999999.99
    Out: 999999.99

    In: 88888.88
    Out: 88888.88

    In: 22222.22
    Out: 22222.22

    In: 33333.33
    Out: 33333.33

    In: 1500.34
    Out: 1500.34

    In: 42345.0
    Out: 42345.0
    ----End Sample Output ----
    , Aug 26, 2005
    #1
    1. Advertising

  2. On 26 Aug 2005 07:55:26 -0700, wrote:

    >In the '80's, Microsoft had a proprietary binary structure to handle
    >floating point numbers, In a previous thread, Bengt Richter posted
    >some example code in how to convert these to python floats;
    >
    >http://groups.google.com/group/comp.lang.python/browse_thread/thread/42150c=
    >cc20a1d8d5/4aadc71be8aeddbe#4aadc71be8aeddbe
    >
    >I copied this code and modified it slightly, however, you will notice
    >that for one of the examples, the conversion isn't exact.
    >

    I suspect a typo in the hex ;-)

    >Can anyone advise me on how to modify this code to correct for this
    >situation ?
    >I think the problem may be related to the different lengths of the
    >mantissa. For double precision (8bytes) MBF format had 55 where as
    >Python floats (IEEE) has only 52 ??

    I believe that's 53 including the "hidden" msb. UIAM that means you
    could lose precision if the LS byte had bits below 'F8' -- i.e.,
    if bytes[0]&7 != 0 in the bytes passed to msd2float.

    But the bits that make the difference between 1234567890.0 and 1234567895.5
    are nowhere near there. Hence my suspicion of a typo.

    >
    >Sample Code Below ----------------------
    ># Conversion of Microsoft Binary Format numbers to Python Floats
    >
    >import binascii as bn
    >import struct as st
    >
    >
    >data =3D [(1234567890,'000000AF052C139F=AD'),

    [(1234567890,'000000A4052C139F=AD'),
    Are you sure it's not a 4? ----^

    > (4069954144,'00000060929672A0'=AD),
    > (999999.99, '703D0AD7FF237494'),
    > ( 88888.88, '400ad7a3709c2d91'),
    > ( 22222.22, '400ad7a3709c2d8f'),
    > ( 33333.33, 'b047e17a54350290'),
    > ( 1500.34, '7814ae47e18a3b8b'),
    > ( 42345.00, '0000000000692590'),
    > ]
    >
    >
    >def msd2float(bytes):
    > #take out values that don't make sense possibly the NaN and
    >Infinity ??
    > if sum(bytes) in [0,72,127]:
    > return 0.0
    > b =3D bytes[:]
    > sign =3D bytes[-2]&0x80
    > b[-2] |=3D 0x80 #hidden most sig bit in place of sign
    > exp =3D bytes[-1] - 0x80 - 56 #exponent offset
    > acc =3D 0L
    > for i,byte in enumerate(b[:-1]):
    > acc |=3D(long(byte)<<(i*8))
    > return (float(acc)*2.0**exp)*((1.,-1.=AD)[sign!=3D0])
    >
    >for line in data:
    > inval =3D line[0]
    > binval =3D bn.unhexlify(line[1])
    > le_bytes =3D list(st.unpack('BBBBBBBB',binv=ADal))
    > outval =3D msd2float(le_bytes)
    > print " In:",inval, "\nOut:",outval,"\n"

    The above print will use str conversion for floats, so you are
    not seeing a full representation of the two values. (BTW, even the repr
    value is not necessarily an accurate representation of the exact
    decimal represented by the IEEE double's bits, but it is guaranteed
    to be converted back to those bits from the literal string representation.)
    E.g. (using my exact decimal hack to show the full value),

    >>> from ut.exactdec import ED
    >>> print .1

    0.1

    Which is the same as
    >>> print str(.1)

    0.1

    but repr shows that's not exact

    >>> print repr(.1)

    0.10000000000000001

    but the exact decimal representation for those bits is
    >>> print ED(.1, 'all')

    ED('0.1000000000000000055511151231257827021181583404541015625')

    >
    >Sample Output ------------------------
    >C:/Python24/pythonw.exe -u "C:/pytest/dms/Test MBF.pyw"
    > In: 1234567890
    >Out: 1234567895.5
    >

    try it with the typo fixed ;-)

    Regards,
    Bengt Richter
    Bengt Richter, Aug 27, 2005
    #2
    1. Advertising

  3. Guest

    Well, thank-you again.
    It's a bit embarassing, but you are correct ... It was a typo on in
    the sample data.
    A bit frustrated with myself as I checked, and double checked, but I
    guess became a bit blinded to the problem.

    Sorry to waste your time, and appreciate your assistance and patience.

    Geoff.
    , Aug 28, 2005
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andy
    Replies:
    7
    Views:
    6,235
    Roedy Green
    May 10, 2004
  2. bd
    Replies:
    0
    Views:
    602
  3. Kosio

    Floats to chars and chars to floats

    Kosio, Sep 16, 2005, in forum: C Programming
    Replies:
    44
    Views:
    1,244
    Tim Rentsch
    Sep 23, 2005
  4. mathieu
    Replies:
    9
    Views:
    729
    James Kanze
    Sep 15, 2007
  5. Carsten Fuchs
    Replies:
    45
    Views:
    1,500
    James Kanze
    Oct 8, 2009
Loading...

Share This Page