Конвертировать MBF Double в IEEE - PullRequest
       31

Конвертировать MBF Double в IEEE

1 голос
/ 22 сентября 2010

Я нашел тему ниже для преобразования MBF в IEEE.

Преобразование MBF одинарного и двойного в IEEE

Любой может объяснить, какова функция кода, помеченногониже?

  1. Тусклый знак As Byte = mbf (6) И ToByte (& H80) 'В чем причина И (& H80)?

  2. Dim exp As Int16 = mbf (7) - 128S - 1S + 1023S 'Почему 1152 (128 + 1 + 1023)?

  3. ieee (7) = ieee (7) Или знак 'Почему бы просто не сохранить знак в ieee (7)?

  4. ieee (7) = ieee(7) Или ToByte (exp >> 4 And & HFF) 'В чем причина сдвига 4?


Public Shared Function MTID(ByVal src() As Byte, ByVal startIndex As Integer) As Double
    Dim mbf(7) As Byte
    Dim ieee(7) As Byte

    Array.Copy(src, startIndex, mbf, 0, 8)

    If mbf(7) <> 0 Then
        Dim sign As Byte = mbf(6) And ToByte(&H80)
        Dim exp As Int16 = mbf(7) - 128S - 1S + 1023S

        ieee(7) = ieee(7) Or sign
        ieee(7) = ieee(7) Or ToByte(exp >> 4 And &HFF)
        ieee(6) = ieee(6) Or ToByte(exp << 4 And &HFF)

        For i As Integer = 6 To 1 Step -1
            mbf(i) <<= 1
            mbf(i) = mbf(i) Or mbf(i - 1) >> 7
        Next
        mbf(0) <<= 1

        For i As Integer = 6 To 1 Step -1
            ieee(i) = ieee(i) Or mbf(i) >> 4
            ieee(i - 1) = ieee(i - 1) Or mbf(i) << 4
        Next
        ieee(0) = ieee(0) Or mbf(0) >> 4
    End If

    Return BitConverter.ToDouble(ieee, 0)
End Function

1 Ответ

6 голосов
/ 22 сентября 2010

Двойной формат IEEE754 состоит из 1-битного знака, 11-битной экспоненты и 52-битной мантиссы:

   7        6        5        4        3        2        1        0
seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm 

Из-за капризов порядка байтов, этот самый старший байт слевана самом деле ieee(7), наименее значимое справа - ieee(0) - то же самое для mbf() ниже.

Показатель степени дает значение от 0 до 2047 (2 11 -1) некоторые из которых используются для представления специальных значений, таких как +/-inf (бесконечность) и nan (не число).

Биты мантиссы представляют слева направо, 1/2, 1/4, 1/8 и так далее.Чтобы получить число, вы вычисляете n = (-1) s x 2 e-bias x 1.m

Двойной двоичный формат Microsoft:1026 *

   7        6        5        4        3        2        1        0
eeeeeeee smmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm

Код, который вы видите, просто переносит (и слегка изменяет) значения из MBF в формат двойной точности IEEE754.

Чтобы ответить на ваши конкретные вопросы:

Dim sign As Byte = mbf(6) And ToByte(&H80)
В чем причина 'And & H80'?

Hex 80 (&H80) является двоичным шаблоном 1000 0000.

Когда вы AND значение с этим, вы получите &H80, если этот бит был установлен или 0 в противном случае.

Это просто записывает, каким был знак числа, и вы можете просто перевести его как есть с mbf(6) на ieee(7).

Dim exp As Int16 = mbf(7) - 128S - 1S + 1023S
Почему 1152 (128 + 1 + 1023)?

Показатели в IEEE754 являются смещенными показателями.Другими словами, сохраненные значения могут быть 0 через 255, но фактические значения, представленные ими, могут быть -128 через 127 (без учета специальных значений на данный момент).

Это позволяет вамиметь отрицательные показатели для очень малых значений и положительные показатели для больших значений.

Показатели MBF также смещены, но они смещены на 128 для одинарного и двойного типов, тогда как показатели двойной точности IEEE754 имеют 0-точка на 1023.

Причина дополнительного -1 заключается в различиях между MBF и IEEE754 относительно того, куда идет неявный 1.IEEE754 ставит его перед двоичной точкой, MBF после.Это означает, что показатель степени должен быть скорректирован на единицу.

ieee(7) = ieee(7) Or sign
Почему бы нам просто не сохранить знак в ieee (7)?

Это небольшая загадка, так как ieee(7) не был явно установлен в этот момент.Я могу только предположить, что ieee() был инициализирован до нуля при создании, иначе вы можете столкнуться с проблемами, поскольку примерно каждая операция передачи здесь выполняется с OR.

You.Вы правы, что имеет больше смысла просто использовать ieee(7) = sign.Фактические значения OR для объединения битов экспоненты приведены в следующей строке.

ieee(7) = ieee(7) Or ToByte(exp >> 4 And &HFF)
В чем причина сдвига на 4?

Поскольку показатель IEEE754 пересекает два байта, и вы хотите, чтобы только часть этого показателя в старшем значащем.Семь битов показателя степени входят в старший значащий байт, остальные четыре входят в следующий байт.

Это обрабатывается двумя строками:

ieee(7) = ieee(7) Or ToByte(exp >> 4 And &HFF) ' upper 7 bits '
ieee(6) = ieee(6) Or ToByte(exp << 4 And &HFF) ' lower 4 bits '

С учетом 16-разрядного значения00000abcdefghijk, рассчитываются два:

>> 4 and &hff : 0abcdefg (s will go at the left)
<< 4 and &hff : hijk0000 (m will go at the right)
...