I have to convert hex
, represeneted as string
s (e.g. \"0xC40C5253\"
) to float values (IEEE-754 conversion). I did not manage
First it needs to be stated the bit-length of the input. Since the hex representation has 4 bytes (8 hex digits), it is most likely a float32
(needs clarification from the asker).
You can parse the bytes from the hex representation into an uint32
using strconv.ParseUint(). ParseUint()
always returns uint64
which uses 8 bytes in memory so you have to convert it to uint32
which uses 4 bytes just like float32
:
s := "C40C5253"
n, err := strconv.ParseUint(s, 16, 32)
if err != nil {
panic(err)
}
n2 = uint32(n)
Now you have the bytes but they are stored in a variable of type uint32
and therefore interpreted as the bytes of an integer. And you want to interpret them as the bytes of a IEEE-754 floating point number, you can use the unsafe package to do that:
f := *(*float32)(unsafe.Pointer(&n2))
fmt.Println(f)
Output (try it on the Go Playground):
-561.2863
Note:
As JimB noted, for the 2nd part (translating uint32
to float32
) the math package has a built-in function math.Float32frombits() which does exactly this under the hood:
f := math.Float32frombits(n2)
The input is 32 bits, so must be treated as a 32-bit number. It is also unsigned, so should be parsed as a uint, not int. Finally, there is no need to use unsafe operations, and in fact as used here they will fail on a machine with a different byte order.
Instead, use math.Float32frombits
, which does exactly what you want:
package main
import (
"fmt"
"math"
"strconv"
)
func main() {
s := "C40C5253"
n, err := strconv.ParseUint(s, 16, 32)
if err != nil {
panic(err)
}
nn := uint32(n)
g := math.Float32frombits(nn)
fmt.Println(g)
}
Output:
-561.2863
http://play.golang.org/p/y1ZjH9pscy
Here are two different approaches that produce -561.2863: http://play.golang.org/p/Y60XB820Ib
import (
"bytes"
"encoding/binary"
"encoding/hex"
"math"
"strconv"
)
func parse_read(s string) (f float32, err error) {
b, err := hex.DecodeString(s)
if err != nil {
return
}
buf := bytes.NewReader(b)
err = binary.Read(buf, binary.BigEndian, &f)
return
}
func parse_math(s string) (f float32, err error) {
i, err := strconv.ParseUint(s, 16, 32)
if err != nil {
return
}
f = math.Float32frombits(uint32(i))
return
}