shadowfiend Posted April 2, 2008 Posted April 2, 2008 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.
/dev/null Posted April 2, 2008 Posted April 2, 2008 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.30000011444092Thanks.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 *
shadowfiend Posted April 2, 2008 Author Posted April 2, 2008 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
/dev/null Posted April 2, 2008 Posted April 2, 2008 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....CheersKurt __________________________________________________________(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 *
shadowfiend Posted April 2, 2008 Author Posted April 2, 2008 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
Zedna Posted April 2, 2008 Posted April 2, 2008 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 Resources UDF  ResourcesEx UDF  AutoIt Forum Search
shadowfiend Posted April 2, 2008 Author Posted April 2, 2008 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!
/dev/null Posted April 2, 2008 Posted April 2, 2008 (edited) 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 April 2, 2008 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 *
shadowfiend Posted April 2, 2008 Author Posted April 2, 2008 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.
shadowfiend Posted April 2, 2008 Author Posted April 2, 2008 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-value25.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.622.8999996185302730 3333B741 335 22.89I 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 EndFuncThanks.Shadowfiend.
wongdong Posted April 3, 2008 Posted April 3, 2008 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
shadowfiend Posted April 3, 2008 Author Posted April 3, 2008 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.
wongdong Posted April 3, 2008 Posted April 3, 2008 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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now