Как конфертировать из поплавка IEEE Python в поплавок Microsoft Basic - PullRequest
3 голосов
/ 15 февраля 2010

Я получил значение с плавающей точкой 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]

Теперь мне нужно повернуть вспять этот процесс, но пока безуспешно. Любая помощь, пожалуйста.

Ответы [ 2 ]

4 голосов
/ 15 февраля 2010

Если вы собираетесь выполнять эти преобразования во время работы под Windows, возможно, быстрее будет загрузить и установить mbf2ieee.exe и вызвать функцию CVS, предлагаемую в результате Mbf2ieee.dll (например, [ctypes] [2]).

Если вы хотите сделать это на чистом Python, я думаю (но я не могу проверить, не имея под рукой номеров MBF), что может сработать следующее (я просто перенес это на Python из C кода) здесь ):

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
0 голосов
/ 09 августа 2010

Ну, я попробовал float2mbf4byte() и сделал 2 модификации:

  1. преобразование отрицательных значений теперь работает,
  2. для Python 2, т. Е. Должен быть список целых, а не строка

Фрагмент:

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