如何将IEEE Python float转换为Microsoft Basic float

时间:2010-02-15 18:47:40

标签: python mbf

我有Python浮点值,我需要将其转换为Microsoft Basic Float(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]

现在我需要扭转这个过程,但还没有成功。请帮忙。

3 个答案:

答案 0 :(得分:4)

如果您要在Windows下运行时执行这些转换,则可以更快地下载并安装mbf2ieee.exe并调用生成的CVS提供的Mbf2ieee.dll功能(例如,通过[ctypes的] [2])。

如果你热衷于使用纯Python,我认为(但我无法测试,手头没有MBF编号),以下内容可能会起作用(我只是从C code here将其移植到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

答案 1 :(得分:0)

好吧,我尝试了float2mbf4byte()并做了两次修改:

  1. 正在转换负值,
  2. 对于Python 2,ieee应该是int的列表,而不是字符串
  3. 摘录:

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

答案 2 :(得分: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:字节必须在范围(0,256)中 因为正确的答案是[0,E4,47,9A],但是 float2mbf4byte给出[0, 228, 19527, 76]。 第三个元素不是字节大小值