Results 1 to 5 of 5

Thread: RESOLVED: Conversion from 2-part 64bit Floating Point to Fixed Point

  1. #1

    Thread Starter
    Member
    Join Date
    Jul 2010
    Posts
    44

    RESOLVED: Conversion from 2-part 64bit Floating Point to Fixed Point

    So I have already figured out how to convert 32-bit (4 byte) Floating Point numbers to Fixed Point using VB's data types from a previous forum thread, in the form shown below-
    Code:
    <StructLayout(LayoutKind.Explicit)> _
        Public Structure DataUnion
            <FieldOffset(0)> Public FloatValue As Single
            <FieldOffset(0)> Public LongValue As Long
            <FieldOffset(0)> Public ByteValue As Byte
        End Structure
    I simply send my value into the Long field and retrieve it from the Single field.

    Now I have a slightly more interesting problem, though- I need to combine (not add, but concatenate) two 4 byte (Single) values into one 8 byte (Double) value, convert to Fixed Point, and round down to Single.

    Here is an example of what I mean:
    I am working with a piece of hardware that outputs values in 8 byte (64-bit, or Double precision) Floating Point numbers. A typical Hex value would be 40 40 DD E4 2D 3B A2 6D. Unfortunately, the hardware that I use for data capture can only receive 4 byte (32-bit, or Single precision) values, so I capture two of them at an offset (i.e. Part 1 is 40 40 DD E4 and Part 2 is 2D 3B A2 6D). There is an added level of complexity, in that the software that is doing the conversion exposes these values (in its API) as decimal values (1077992932 and 758882925 would be my inputs in this example), so I have to convert them to another form first to even combine them.

    When I convert the 8-byte number by hand, I get the proper decimal fixed point value (roughly 33.733 or so) but I'm not really sure how to convert to the proper data type and combine these values in VB. Has anyone done this before?
    Last edited by pgm575; Jul 20th, 2011 at 04:47 PM. Reason: Resolved problem

  2. #2

    Thread Starter
    Member
    Join Date
    Jul 2010
    Posts
    44

    Re: Conversion from 2-part 64bit Floating Point to Fixed Point

    So I've gotten closer but I'm not quite there yet. What I have attempted to do is convert my two singles to hexadecimal representations, combine them as strings, and I will then convert them back. This code is shown below, in its entirety-

    FLOAT CONVERT Code:
    1. Imports Microsoft.Win32
    2. Imports System.Runtime.InteropServices
    3.  
    4. Module Module1
    5.  
    6.     <StructLayout(LayoutKind.Explicit)> _
    7.     Public Structure DataUnion
    8.         <FieldOffset(0)> Public FloatValue As Single
    9.         <FieldOffset(0)> Public FloatLongValue As Double
    10.         <FieldOffset(0)> Public LongValue As Long
    11.         <FieldOffset(0)> Public ByteValue As Byte
    12.     End Structure
    13.  
    14.     Sub Main()
    15.         Dim p1 As Single, p2 As Single
    16.         Dim ba1() As Byte, ba2() As Byte, wholeByte(7) As Byte
    17.         Dim hex1 As String, hex2 As String, whole As String
    18.         Dim suLong As Int64
    19.         Dim su As DataUnion
    20.  
    21.         p1 = 1077992931
    22.         ba1 = BitConverter.GetBytes(p1)
    23.         hex1 = BitConverter.ToString(ba1)
    24.  
    25.         p2 = 831725571
    26.         ba2 = BitConverter.GetBytes(p2)
    27.         hex2 = BitConverter.ToString(ba2)
    28.  
    29.         whole = hex1 + "-" + hex2
    30.         ba1.CopyTo(wholeByte, 0)
    31.         ba2.CopyTo(wholeByte, 4)
    32.  
    33.         Console.WriteLine("Part 1 is {0}d and part 2 is {1}d" & vbCrLf, p1, p2)
    34.  
    35.         Console.WriteLine("Part1 byte array is {0}", hex1)
    36.         Console.WriteLine("Part2 byte array is {0}", hex2)
    37.         Console.WriteLine("Whole byte array is {0}", whole)
    38.  
    39.         Console.WriteLine(vbCrLf)
    40.  
    41.         suLong = BitConverter.ToInt64(wholeByte, 0)
    42.         su.LongValue = suLong
    43.  
    44.         Console.WriteLine("suLong is {0} and su.LongValue is {1}", suLong, su.LongValue)
    45.         Console.WriteLine("su.FloatValue is {0}", su.FloatValue)
    46.     End Sub
    47.  
    48. End Module

    Unfortunately, when I run this Console application I get incorrect Hex values. For example, "Part1" is correctly converted by Windows Calculator to 40 40 DD E2, whereas this console application converts it to BC 81 80 4E. The MS documentation states that GetBytes method returns a byte array of the given value, so does anyone see what I'm missing here?

  3. #3

    Thread Starter
    Member
    Join Date
    Jul 2010
    Posts
    44

    Re: Conversion from 2-part 64bit Floating Point to Fixed Point

    Alright, more progress but still not quite there. If the above p1 = 1077992931d is used and I implement the code
    Additional Lines Code:
    1. Dim samp1 As String = Hex(p1)
    2. Console.WriteLine("Part1 converted to Hex directly is {0}", samp1)
    at the bottom of my Main Sub, then I get an output of 40 40 DE 00h. This converts back to 1077992960d, but I would've expected to see 40 40 DD E3h as the output.

    Given the decimal values I'm seeing, this looks less like rounding and more like a different conversion method. It needs to be exactly accurate, though, since I'm combining these representations to make that one 64-bit number.

  4. #4

    Thread Starter
    Member
    Join Date
    Jul 2010
    Posts
    44

    Re: Conversion from 2-part 64bit Floating Point to Fixed Point

    So now I've gotten the pieces to convert correctly but the whole Hex value does not convert back to decimal properly. See code below.

    Code:
    Imports Microsoft.Win32
    Imports System.Runtime.InteropServices
    
    Module Module1
    
        <StructLayout(LayoutKind.Explicit)> _
        Public Structure DataUnion
            <FieldOffset(0)> Public FixedPointValue As Single
            <FieldOffset(0)> Public LongValue As Long
            <FieldOffset(0)> Public ByteValue As Byte
        End Structure
    
        Sub Main()
            Dim p1 As Int32, p2 As Int32
            Dim wholeByte2(7) As Byte
            Dim su As DataUnion
    
            p1 = 1077992931 'properly converts to 40 40 DD E3h
            p2 = 831725571 'properly converts to 31 93 20 03h
    
            Dim samp1 As String = Hex(p1), samp2 As String = Hex(p2), wholeHexStr As String = samp1 & samp2
    
            Console.WriteLine("Part1 converted to Hex directly is {0}. Part 2 is {1}.", samp1, samp2)
            Console.WriteLine("Whole is {0}.", wholeHexStr)
    
            Dim j As Integer = 0
            For i = 0 To wholeHexStr.Length - 2
                wholeByte2(j) = Byte.Parse(wholeHexStr.Substring(i, 2), Globalization.NumberStyles.HexNumber)
                i += 1
                j += 1
            Next
            Console.WriteLine("Whole with splits as usable value is {0}.", BitConverter.ToString(wholeByte2))
            Console.WriteLine(vbCrLf)
    
            Dim ConLong As Long = BitConverter.ToInt64(wholeByte2, 0) 'should convert to 4629944384795910146d
            'actually converts to 225341823854133312d
            su.LongValue = ConLong
            Console.WriteLine("Complete Long in structure is {0}", su.LongValue)
            Console.WriteLine("Converted value is {0}", su.FixedPointValue)
        End Sub
    
    End Module
    Anyone know why my Byte-to-Long conversion isn't working as expected?

  5. #5

    Thread Starter
    Member
    Join Date
    Jul 2010
    Posts
    44

    Re: Conversion from 2-part 64bit Floating Point to Fixed Point

    Ended up resolving this myself. Looks like the Hex() method was converting in Big Endian format, whereas the number structure was converting in Little Endian format. The proper conversion is shown below.

    Code:
    Imports Microsoft.Win32
    Imports System.Runtime.InteropServices
    
    Module Module1
    
        <StructLayout(LayoutKind.Explicit)> _
        Public Structure DataUnion
            <FieldOffset(0)> Public FixedPointValue As Double
            <FieldOffset(0)> Public LongValue As Long
            <FieldOffset(0)> Public ByteValue As Byte
        End Structure
    
        Sub Main()
            Dim p1 As Int32, p2 As Int32
            Dim wholeByte(7) As Byte
            Dim su As DataUnion
            Dim TempValue As Double, FinalValue As Single
    
            p1 = 1077992931 'properly converts to 40 40 DD E3h
            p2 = 831725571 'properly converts to 31 93 20 03h
    
            Dim samp1 As String = Hex(p1), samp2 As String = Hex(p2), wholeHexStr As String = samp1 & samp2
    
            Console.WriteLine("Part1 converted to Hex directly is {0}. Part 2 is {1}.", samp1, samp2)
            Console.WriteLine("Whole is {0}.", wholeHexStr)
    
            Dim j As Integer = 0
            For i = 0 To wholeHexStr.Length - 2
                wholeByte(7 - j) = Byte.Parse(wholeHexStr.Substring(i, 2), Globalization.NumberStyles.HexNumber)
                i += 1
                j += 1
            Next
            Console.WriteLine("Whole with splits as system-usable value is {0}.", BitConverter.ToString(wholeByte))
            Console.WriteLine(vbCrLf)
    
            Dim ConLong As Long = (BitConverter.ToInt64(wholeByte, 0)) 'properly converts to 4629944384795910147d
            su.LongValue = ConLong
            Console.WriteLine("Complete Long in structure is {0}", su.LongValue) '4629944384795910147d
            Console.WriteLine("Which happens to be {0} in Hex", Hex(su.LongValue)) '40 40 DD E3 31 93 20 03h
    
            TempValue = su.FixedPointValue
            Console.WriteLine("Converted value is {0}", TempValue)
            FinalValue = Convert.ToSingle(TempValue)
            Console.WriteLine("Final value is {0}", FinalValue)
        End Sub
    
    End Module

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width