469,907 Members | 2,214 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,907 developers. It's quick & easy.

Converting from Microsoft Binary Format floats to Python Float

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....adc71be8aeddbe

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 '05 #1
2 3271
On 26 Aug 2005 07:55:26 -0700, ge********@hotmail.com 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....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.10000000000000000555111512312578270211815834 04541015625')

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
Aug 27 '05 #2
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 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by Dan Stromberg | last post: by
8 posts views Thread by Rick | last post: by
2 posts views Thread by Matt McGonigle | last post: by
10 posts views Thread by 63q2o4i02 | last post: by
8 posts views Thread by Ronin | last post: by
9 posts views Thread by Gregory.A.Book | last post: by
4 posts views Thread by Mason | last post: by
reply views Thread by Salome Sato | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.