tags:

views:

94

answers:

3

I've got some legacy data which is still in use, reading the binary files is not the problem, the number format is. All floating point numbers are saved in MBF format (Single and Double). I've found a topic about that on the MSDN boards but that one only deals with Single values. I'd also would like to stay away from API-Calls as far as I can.

Does anyone have a solution for Doubles?

Edit: Just in case somebody needs it, here is the VB.NET Code (it's Option Strict compliant) I ended up with (feel free to convert it to C# and edit it in):

''' <summary>Converts a MBF Single to an IEEE Single</summary>
''' <param name="src">The MBF Single value</param>
''' <returns>The converted IEEE Single value</returns>
''' <remarks>Here can find some further information about this topic: http://en.wikipedia.org/wiki/Microsoft_Binary_Format http://support.microsoft.com/kb/140520&lt;/remarks&gt;
Public Shared Function MTIS(ByVal src As Single) As Single
    Return MTIS(BitConverter.GetBytes(src), 0)
End Function

''' <summary>Converts a MBF Single to an IEEE Single</summary>
''' <param name="src">The source array</param>
''' <param name="startIndex">The start index at which the Single starts</param>
''' <returns>The converted IEEE Single value</returns>
''' <remarks>Here can find some further information about this topic: http://en.wikipedia.org/wiki/Microsoft_Binary_Format http://support.microsoft.com/kb/140520&lt;/remarks&gt;
Public Shared Function MTIS(ByVal src() As Byte, ByVal startIndex As Integer) As Single
    Dim mbf(3) As Byte
    Dim ieee(3) As Byte

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

    If mbf(3) <> 0 Then
        Dim sign As Byte = mbf(2) And ToByte(&H80)
        Dim exp As Byte = mbf(3) - ToByte(2) ' -1-128-127 '

        ieee(3) = ieee(3) Or sign
        ieee(3) = ieee(3) Or exp >> 1
        ieee(2) = ieee(2) Or exp << 7
        ieee(2) = ieee(2) Or mbf(2) And ToByte(&H7F)
        ieee(1) = mbf(1)
        ieee(0) = mbf(0)
    End If

    Return BitConverter.ToSingle(ieee, 0)
End Function


''' <summary>Converts a MBF Double to a IEEE Double</summary>
''' <param name="src">The MBF Double value</param>
''' <returns>The converted IEEE Double value</returns>
''' <remarks>Here can find some further information about this topic: http://en.wikipedia.org/wiki/Microsoft_Binary_Format http://support.microsoft.com/kb/140520&lt;/remarks&gt;
Public Shared Function MTID(ByVal src As Double) As Double
    Return MTID(BitConverter.GetBytes(src), 0)
End Function

''' <summary>Converts a MBF Double to a IEEE Double</summary>
''' <param name="src">The source array</param>
''' <param name="startIndex">The start index at which the Double starts</param>
''' <returns>The converted IEEE Double value</returns>
''' <remarks>Here can find some further information about this topic: http://en.wikipedia.org/wiki/Microsoft_Binary_Format http://support.microsoft.com/kb/140520&lt;/remarks&gt;
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  A: 

At this Wiki page there's links to a few different code samples for doing this in C, C++ and Python.

One or more of those should hopefully be relatively easy to convert to some language that suits you.

ho1
+1  A: 

Microsoft has published a KB article about this, including a P/Invokable DLL which you can use to make the conversion from MBF to IEEE.

http://support.microsoft.com/kb/140520

code4life
A: 

Thanks for your code, it is useful.

However, could you explain below codes for me in detail, please?

Thank you!

If mbf(7) <> 0 Then
    Dim sign As Byte = mbf(6) And ToByte(&H80)    **'What is the function AND (&H80)?**
    Dim exp As Int16 = mbf(7) - 128S - 1S + 1023S **'Why is 1152 (128+1+1023)?**

    ieee(7) = ieee(7) Or sign                     **'Why don't just save sign to ieee(7)?**
    ieee(7) = ieee(7) Or ToByte(exp >> 4 And &HFF) **'What is the reason to shift 4 bits?**
    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 
Chiu
To be honestly, I have no freaking idea how that works. I knocked it of some C++ code I found on a Microsoft Support Site (I think). I also found quiet a few ways to convert those, but this one seemed like the easiest debug/convertible one. You might create your own question in which you ask for further explanation of this code and the format. But...the `And` is a bitwise `And`, so it does null everything except the first bit of `mbf(6)`, so `sign` is either 0 or 128.
Bobby