开发者

How to convert from IEEE Python float to Microsoft Basic float

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 fm开发者_如何学运维sbin2ieee(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.


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


Well, I tried float2mbf4byte() and made 2 modifications:

  1. converting negative values is now working,
  2. 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))


The mbf2ieee failed to convert properly, try this one:

import struct

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

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', bytearray(ieee))[0]


print(mbf2ieee(bytearray(float2mbf4byte(52400126))))

... and you will get:

builtins.ValueError: byte must be in range(0, 256) because the right answer is [0,E4,47,9A], but float2mbf4byte gives [0, 228, 19527, 76] . 3rd element is not a byte size value


#Converter between MSF and IEEE
import struct

def fmsbin2ieee(b):
    as_int = struct.unpack('i', b)
    if not as_int:
        return 0.0
    man = int(struct.unpack('H', b[2:])[0])
    if not man:
        return 0.0
    exp = (man & 0xff00) - 0x0200
    man = man & 0x7f | (man << 8) & 0x8000
    man |= exp >> 1

    bytes2 = bytes([b[0], b[1], (man & 255), ((man >> 8) & 255)])
    return struct.unpack('f', bytes2)[0]

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 bytes(msbin)

if __name__ == '__main__':
    key = bytes([0x13, 0x00, 0x10, 0x10])
    print(type(key))
    print(key)

    # 4 bytes MBF to float IEEE
    flIEEE = fmsbin2ieee(key)
    print(type(flIEEE))
    print("ieee=", flIEEE)

    # float IEEE to 4 bytes MBF
    msf = float2mbf4byte(flIEEE)
    print(type(msf))
    print(msf)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜