Jump to content

Help converting Hex 32 bit float please?


Recommended Posts

Hi everyone, I have looked high and low and not found anything that I can use. I want a function to convert a hex 32 bit float (little endian) to decimal.

For example 6766CA41 = 25.30000011444092

Thanks.

Shadowfiend.

what is the encoding format?

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

Erm, I'm not quite sure what you mean by encoding format. I am reading in the hex number from a binary file using...

Func PricipitationRate();grab Pricipitation Rate (float)
         $PricipitationRatePos = (((($csgNo - 1) * 99) + $stationNo - 1) * 59) + 40;the + 40 is the offset (Nth chr from start of field)
         $Hex = BinaryMid($CopyStationschars, $PricipitationRatePos, 4);grab 4 bytes for float
         $Hex = StringReplace($Hex,"0x","");Remove all the 0x hex prefixes from the string
             $PricipitationRateString = ;CONVERSION  FUNCTION  GOES  HERE 
 EndFunc
Link to comment
Share on other sites

Erm, I'm not quite sure what you mean by encoding format.

hm... maybe you should start by reading this: http://en.wikipedia.org/wiki/IEEE_754. Without knowledge of the encoding format, you cannot convert it....

Cheers

Kurt

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

Ok Kurt, here's what I know.

When using the hex editer/viewer XVI32 the data inspector correctly converts the value in my binary file 67 66 CA 41 = 25.30000011444092 (this is the same as the decimal value in the database program from which the binary file was generated, oh and by the way it was written in c++)

The settings are for "Little Endian (Intel)" and the discription of the format is "IEEE Single (32 bit)"

I have was looking at the IEEE 754 Wikipedia artical before I posted and cannot understand it! Sorry but I have been trying :)

Thanks,

Shadowfiend

Link to comment
Share on other sites

Here is conversion function from Auto3Library.

Maybe it can help you as idea:

Func _Lib_FloatToInt($nFloat)
  Local $tFloat, $tInt

  $tFloat  = DllStructCreate("float")
  $tInt = DllStructCreate("int"  , DllStructGetPtr($tFloat))
  DllStructSetData($tFloat, 1, $nFloat)
  Return DllStructGetData($tInt, 1)
EndFunc
Link to comment
Share on other sites

Thanks Zenda, can you tell me what this function does? Just to see what happened I tried this.

$Hex = "6766CA41"
 
 $Result = _Lib_FloatToInt($Hex)
 
 MsgBox(0,"result =", $Result)
 
 Func _Lib_FloatToInt($nFloat)
   Local $tFloat, $tInt
 
   $tFloat  = DllStructCreate("float")
   $tInt    = DllStructCreate("int"  , DllStructGetPtr($tFloat))
   DllStructSetData($tFloat, 1, $nFloat)
   Return DllStructGetData($tInt, 1)
 EndFunc

It returns '0'. I'm finding this a bit tough!

Link to comment
Share on other sites

Thanks Zenda, can you tell me what this function does? Just to see what happened I tried this.

It returns '0'. I'm finding this a bit tough!

#Include <WinAPI.au3>

func endian_converter($value)

    local $byte0 = BitShift($value,24) 
    local $byte1 = BitAND(BitShift($value,-8), 0x00FF0000)
    local $byte2 = BitAND(BitShift($value,8), 0x0000FF00)
    local $byte3 = BitShift($value,-24) 

    local $result = BitOR($byte0,$byte1,$byte2,$byte3)

    return $result

endfunc 

MsgBox(0,"",StringFormat("%2.16f",_WinAPI_IntToFloat(endian_converter(0x6766CA41))))

EDIT: And if you are reading the HEX string from a file....

#Include <WinAPI.au3>
#Include <String.au3>

func endian_converter($value)

    local $byte0 = BitShift($value,24) 
    local $byte1 = BitAND(BitShift($value,-8), 0x00FF0000)
    local $byte2 = BitAND(BitShift($value,8), 0x0000FF00)
    local $byte3 = BitShift($value,-24) 

    local $result = BitOR($byte0,$byte1,$byte2,$byte3)

    return $result

endfunc 

$Hex = "6766CA41"

MsgBox(0,"",StringFormat("%2.16f",_WinAPI_IntToFloat(endian_converter(Number("0x" & $Hex)))))

Cheers

Kurt

Edited by /dev/null

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

Kurt that's fantastic! I hav'nt integrated this into my script yet but I have looked at the code you posted and it indeed produces the correct answer. Very tidy.

I take it that all of the AutoIT binary functions use big endian?

Tell me, did you create the endian_converter yourself? I will study and learn from this, I think this will help me to understand the 32 bit float format as well.

Thank you Kurt, thank you Zedna! :)

Shadowfiend.

Link to comment
Share on other sites

Huston I have a problem. I have been trying all sorts to figure this out. Here is the output from my script. The Pricipitation Rate returns the correct answer **sometimes**! At other values I get '-1.#QNAN00000000000'

Pricipitation-Rate Hex chr-position actual-dec-value

25.3000011444091800 6766CA41 40 25.3

-1.#QNAN00000000000 9A99C541 99 24.7

-1.#QNAN00000000000 CDCCC441 158 24.6

-1.#QNAN00000000000 CDCCC041 217 24.1

-1.#QNAN00000000000 CDCCBC41 276 23.6

22.8999996185302730 3333B741 335 22.89

I hope you can read it ok I can't seem to make the spacing work. The actual-dec-value was inputted by hand.

Here is my function.

Func PricipitationRate();grab Pricipitation Rate (float)
         $PricipitationRatePos = (((($csgNo - 1) * 99) + $stationNo - 1) * 59) + 40;the + 40 is the offset (Nth chr from start of field)
         $Hex = BinaryMid($CopyStationschars, $PricipitationRatePos, 4);grab 4 bytes for float
         $Hex = StringReplace($Hex,"0x","");Remove all the 0x hex prefixes from the string
             $PricipitationRateString = StringFormat("%2.16f",_WinAPI_IntToFloat(endian_converter(Number("0x" & $Hex)))) & " " & $Hex & " " & $PricipitationRatePos
 EndFunc

Thanks.

Shadowfiend.

Link to comment
Share on other sites

Hi there. I actually needed the same and implemented a converter (all in autoit). If you like it, feel free to try it. But it is pretty slow (1ms/conversion) so i'll see if i can speed it up with the code found here.

CODE
#Include <WinAPI.au3>

#include <String.au3>

$begin = TimerInit()

for $i = 1 to 1000

$Sepp = HextoFloat(0x3C0AF90D)

next

$dif = TimerDiff($begin)

MsgBox(0,"Speed",$dif)

func HextoFloat($HexNumber)

local $result = 0;

local $exponent = 0;

local $result = 0;

local $current = 23;

local $vorkomma = 0;

local $nachkomma = 0;

;First calcualte the Exponenten

For $i = 24 to 31

$exponent = $exponent + BitIsSet($HexNumber, $i)*(2^($i-24))

Next

$exponent = $exponent - 127;

;Positive Exponenets: 1 is added to the pre-comma number

if $exponent > -1 Then

$vorkomma = 1;

While ($exponent > 0)

$vorkomma = $vorkomma * 2 + BitIsSet($HexNumber,$current)

$current = $current - 1;

$exponent = $exponent - 1;

WEnd

$exponent = -1

Else

; Set the post-komma to the first occurence of a 1 (filled)

$nachkomma = 2^$exponent

$exponent = $exponent -1

EndIf

; read the rest of the number in the post-komma

while $current > 0

$nachkomma = $nachkomma+(BitIsSet($HexNumber, $current)*(2^$exponent))

$exponent = $exponent -1

$current = $current-1

WEnd

$result = $vorkomma + $nachkomma;

if (BitIsSet($HexNumber, 32) = 1) then

return ($result * -1)

else

return $result

EndIf

Endfunc

func BitIsSet($Hex, $element)

; mask all but this single Bit

local $temp = BitAND($Hex, 2^($element-1))

Return (BitShift($temp,($element-1)))

EndFunc

Link to comment
Share on other sites

Hi wongdong, typically just as I found my own solution, I find your post! I dare say that my method is probably re-inventing the wheel but it works! Thanks for your code. Wow this is doing the whole conversion! That could be very usefull to help me understand how floats work.

Here are my working functions.

Func PricipitationRate();grab Pricipitation Rate (float)
 $PricipitationRatePos = (((($csgNo - 1) * 99) + $stationNo - 1) * 59) + 40;the + 40 is the offset (Nth chr from start of field)
 $Hex = BinaryMid($CopyStationschars, $PricipitationRatePos, 4);grab 4 bytes for float
 $Hex = StringReplace($Hex,"0x","");Remove all the 0x hex prefixes from the string
 $Hex = endian_converter($Hex);Swap byte order
 $PricipitationRateString = StringFormat("%2.16f",_WinAPI_IntToFloat(Number("0x" & $Hex)));This does the float conversion
 $PricipitationRateString = Round($PricipitationRateString, 2);Round to 2 decimal places
         EndFunc
         
         Func endian_converter($Hex_Value);My endian converter swaps the byte order
         Local $temp1 = StringMid($Hex_Value, 1, 2)
         Local $temp2 = StringMid($Hex_Value, 3, 2)
         Local $temp3 = StringMid($Hex_Value, 5, 2)
         Local $temp4 = StringMid($Hex_Value, 7, 2)
         Return $temp4 & $temp3 & $temp2 & $temp1
         EndFunc

Kurt, it looks like your endian_converter function is doing a bit-wise rotation? What I needed was byte rotation. Thanks all the same though.

Cheers,

Shadowfiend.

Link to comment
Share on other sites

Hi wongdong, typically just as I found my own solution, I find your post! I dare say that my method is probably re-inventing the wheel but it works! Thanks for your code. Wow this is doing the whole conversion! That could be very usefull to help me understand how floats work.

Yeah, i know :) The other solutions (with pointers and WINAPI) are much better, i use them myself.

Cheers, WD

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...