3

我得到了 Python 浮点值,我需要将其转换为 Microsoft 基本浮点 (MBF) 格式。幸运的是,从互联网上得到了一些相反的代码。

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]

现在我需要扭转这个过程,但还没有成功。请提供任何帮助。

4

4 回答 4

4

如果您要在 Windows 下运行时执行这些转换,更快的方法可能是下载并安装mbf2ieee.exe并调用CVS结果提供的函数Mbf2ieee.dll(例如通过 [ctypes][2])。

如果您热衷于在纯 Python 中执行此操作,我认为(但我无法测试,手头没有 MBF 数字)以下可能有效(我只是将其从C 代码移植到 Python 此处):

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]

如果这有问题,你能举一些输入值和预期结果的例子吗?

编辑:如果它是你想要的反向功能,它应该是:

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
于 2010-02-15T19:21:11.440 回答
0

好吧,我尝试float2mbf4byte()并进行了 2 处修改:

  1. 转换负值现在正在工作,
  2. 对于 Python 2,ieee 应该是 int 的列表,而不是字符串

片段:

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))
于 2010-08-09T15:12:58.977 回答
0
#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)
于 2022-01-10T18:23:59.313 回答
0

mbf2ieee 无法正确转换,试试这个:

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))))

...你会得到:

builtins.ValueError: byte must be in range(0, 256) 因为正确答案是[0,E4,47,9A],但 float2mbf4byte 给出[0, 228, 19527, 76]. 第三个元素不是字节大小值

于 2020-12-11T01:17:32.837 回答