Displaying hexadecimal data as float. What sort of result are you after?

My setup is: SQL Server 2005, Visual Web Developer 2005 Express (VB)

I have a SQL Server database that gets a large C++ data structure that contains longs and floats serialized as an ASCII string where all bytes were converted to hex. The bytes have to be reversed because of endieness. I have been tasked with creating a page to dispaly the parsed data. I know that I can extract the data in groups of 4 (for the longs) and 8 (for the floats). I can convert the hex to decimal, but it is converting to a very large integer type value instead of the expected decimal. I have tried to search the web, but have found very little to aid. The closest used a function similar to the C++ memcpy. This did not seem to be available in my case.

A sample of the code is here:
MyDataReader.Read()
' extract the data
Dim dataString As String
Dim tempString As String
Dim counter As Long
Dim tempInt As Long
Dim tempFloat As Double

counter = 0
dataString = CStr(MyDataReader("fld_Curve_Data"))

Dim tRow As New TableRow()

tempString = "&H" + dataString.Substring(counter + 2, 1) + dataString.Substring(counter + 3, 1) + dataString.Substring(counter + 0, 1) + dataString.Substring(counter + 1, 1)
tempInt = CInt(tempString)
counter = counter + 4

tempString = "&H" + dataString.Substring(counter + 2, 1) + dataString.Substring(counter + 3, 1) + dataString.Substring(counter + 0, 1) + dataString.Substring(counter + 1, 1)
tempInt = Val(tempString)
counter = counter + 4

Dim tCell0 As New TableCell()
tCell0.Text = CStr(tempInt)
tRow.Cells.Add(tCell0)

tempString = "&H" + dataString.Substring(counter + 2, 1) + dataString.Substring(counter + 3, 1) + dataString.Substring(counter + 0, 1) + dataString.Substring(counter + 1, 1)
tempInt = Val(tempString)
counter = counter + 4

Dim tCell1 As New TableCell()
tCell1.Text = CStr(tempInt)
tRow.Cells.Add(tCell1)

tempString = "&H" + dataString.Substring(counter + 6, 1) + dataString.Substring(counter + 7, 1) + dataString.Substring(counter + 4, 1) + dataString.Substring(counter + 5, 1) + dataString.Substring(counter + 2, 1) + dataString.Substring(counter + 3, 1) + dataString.Substring(counter + 0, 1) + dataString.Substring(counter + 1, 1)
tempFloat = Val(tempString)
counter = counter + 8

Dim tCell2 As New TableCell()
tCell2.Text = CStr(tempFloat)
tRow.Cells.Add(tCell2)

[2507 byte] By [Mojosound] at [2007-12-28]
# 1

Hi,

Referring to this thread.>>

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1110597&SiteID=1

I tried.>>

Dim hex As String
hex = "ABCDEF0123456789"
Dim i As Int64
i = Convert.ToInt64(hex, 16) '16 is the base
MsgBox(CStr(i))

Windows calculator returns.>>

12,379,813,738,877,118,345

but this convert function returns>> -6,066,930,334,832,433,271

which isn't even near half the value as a negative number, what's going on?

Half is.>> 6,189,906,869,438,559,172.5

Sussed it.>>

7FFFFFFFFFFFFFFF is the maximum HEX value before the sign turns negative

due to the sign bit. 7F being 127 in the 1st BYTE of the string.

Regards,

S_DS

P.S. Which result are you needing?

Spidermans_DarkSide at 2007-9-4 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 2
Thanks, but that was not what I was looking for.

From searching the web it looks like I need to set the hex string as a byte array and then copy the memory. There are a few sites that list this as the function to use:

Public Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (ByVal Destination As Any, ByVal Source As Any, _
ByVal Length As Long)

I read in another post that As Any is no longer supported and thaht I should change to this:

Public Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (ByVal Destination As Integer, ByVal Source As Integer, _
ByVal Length As Long)

I now have a converter function that looks like this (slightly modified from one I found online):

Private Function Convert(ByVal HexDouble As String) As Double
Dim n As Long
Dim b(0 To 7) As Byte
Dim f As Double

If Not IsNumeric("&H" & HexDouble) _
Or Len(HexDouble) <> 8 Then
MsgBox("Invalid Value.")
Else
For n = 0 To 7
Dim tempString As String
tempString = "&H" + HexDouble.Substring(n, 1)
b(n) = Val(tempString)
Next n
CopyMemory(f, b(0), 8)
Convert = f
End If

End Function

I now end up with a memory access error - Attempted to read or write protected memory.

Any ideas?

Mojosound at 2007-9-4 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 3

Yeah, don't do that - you will mess up memory. oops! you just did...

If I read correctly, you have a string, which is a hexadecimal value representation of a single value. Just off the top of my head, how about something like this - convert it to an integer base 16, then convert to bytes, then convert the bytes to a single:

Dim s As String = "acf0"

Dim i As Integer = Convert.ToInt32(s, 16)

Debug.WriteLine(i)

Dim d As Single = BitConverter.ToSingle(BitConverter.GetBytes(i), 0)

Debug.WriteLine(d)

May not be exactly what you need (sounds like you need doubles), but there may be something you can use in the BitConverter Methods.

SJWhiteley at 2007-9-4 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 4

okay: using 8 bytes and a double result....

Dim s As String = "acf0ca21"

Dim i As Long = Convert.ToInt64(s, 16)

Debug.WriteLine(i)

Dim b() As Byte

b = BitConverter.GetBytes(i)

Dim d As Double = BitConverter.ToDouble(b, 0)

Debug.WriteLine(d)

Or as a one-liner (for the one-liner-freaks out there ):

Dim r As Double = BitConverter.ToDouble(BitConverter.GetBytes(Convert.ToInt64(s, 16)), 0)

(This was supposed to be an edit to the last post, but the internet threw a wobbly for a few moments...)

SJWhiteley at 2007-9-4 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 5
Thanks, it all works like magic :)
Mojosound at 2007-9-4 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 6

Mojosound wrote:
Thanks, it all works like magic :)

Ah, you must have added the System.Magic namespace: that'll solve the problem

SJWhiteley at 2007-9-4 > top of Msdn Tech,Visual Basic,Visual Basic Language...