问题
I got Python float value and I need to convert it in to Microsoft Basic Float (MBF) format. Luckily, Got some code from internet that does the reverse.
def fmsbin2ieee(self,bytes):
"""Convert an array of 4 bytes containing Microsoft Binary floating point
number to IEEE floating point format (which is used by Python)"""
as_int = struct.unpack("i", bytes)
if not as_int:
return 0.0
man = long(struct.unpack('H', bytes[2:])[0])
exp = (man & 0xff00) - 0x0200
if (exp & 0x8000 != man & 0x8000):
return 1.0
#raise ValueError('exponent overflow')
man = man & 0x7f | (man << 8) & 0x8000
man |= exp >> 1
bytes2 = bytes[:2]
bytes2 += chr(man & 255)
bytes2 += chr((man >> 8) & 255)
return struct.unpack("f", bytes2)[0]
Now I need to reverse this process, but no success yet. Any help please.
回答1:
If you're going to perform these conversions while running under Windows, faster might be to download and install mbf2ieee.exe and call the CVS
function offered by the resulting Mbf2ieee.dll
(e.g. via [ctypes][2]).
If you're keen to do it in pure Python, I think (but I can't test, having no MBF numbers at hand) that the following might work (I just ported it to Python from C code here):
def mbf2ieee(mbf_4bytestring):
msbin = struct.unpack('4B', mbf_4bytestring)
if msbin[3] == 0: return 0.0
ieee = [0] * 4
sign = msbin[2] & 0x80
ieee_exp = msbin[3] - 2
ieee[3] = sign | (ieee_exp >> 1)
ieee[2] = (ieee_exp << 7) | (msbin[2] & 0x7f)
ieee[:2] = msbin[:2]
return struct.unpack('f', ieee)[0]
If this has problems, can you give some examples of input values and expected results?
Edit: if it's the reverse function you want, it should be:
def float2mbf4byte(f):
ieee = struct.pack('f', f)
msbin = [0] * 4
sign = ieee[3] & 0x80
msbin_exp = (ieee[3] << 1) | (ieee[2] >> 7)
# how do you want to treat too-large exponents...?
if msbin_exp == 0xfe: raise OverflowError
msbin_exp += 2
msbin[3] = msbin_exp
msbin[2] = sign | (ieee[2] & 0x7f)
msbin[:2] = ieee[:2]
return msbin
回答2:
Well, I tried float2mbf4byte()
and made 2 modifications:
- converting negative values is now working,
- for Python 2, ieee should be list of int's, not string
The snippet:
def float2mbf4byte(f):
ieee = [ord(s) for s in struct.pack('f', f)]
msbin = [0] * 4
sign = ieee[3] & 0x80
ieee[3] &= 0x7f
msbin_exp = (ieee[3] << 1) | (ieee[2] >> 7)
# how do you want to treat too-large exponents...?
if msbin_exp == 0xfe: raise OverflowError
msbin_exp += 2
msbin[3] = msbin_exp
msbin[2] = sign | (ieee[2] & 0x7f)
msbin[:2] = ieee[:2]
return msbin
def ieee2fmsbin(f):
return struct.pack('4B', *float2mbf4byte(f))
来源:https://stackoverflow.com/questions/2268191/how-to-convert-from-ieee-python-float-to-microsoft-basic-float