How to convert a hex to floating
I need to convert hex
, represented as string
(for example "0xC40C5253"
) for floating point values (IEEE-754 conversion). I was unable to do this using the strconv.ParseFloat function. Is there anything else I need to use? I could not find it until now. I also tried converting it to an integer first and then to a float, but the results were wrong.
My last try code:
package main
import (
"fmt"
"strconv"
)
func main () {
x, err := strconv.ParseInt("C40C5253", 16, 64)
f, err := strconv.ParseFloat(fmt.Sprintf("%d", x), 64)
if err != nil {
fmt.Printf("Error in conversion: %s\n", err)
} else {
fmt.Println(f)
}
}
source to share
First you need to specify the bit length of the input. Since the hexadecimal representation is 4 bytes (8 hexadecimal digits) this is most likely float32
(needs clarification from the questioner).
You can parse bytes from hexadecimal to uint32
using . always returns which uses 8 bytes in memory, so you have to convert it to which uses 4 bytes like : strconv.ParseUint()
ParseUint()
uint64
uint32
float32
s := "C40C5253"
n, err := strconv.ParseUint(s, 16, 32)
if err != nil {
panic(err)
}
n2 = uint32(n)
You now have bytes, but they are stored in a type variable uint32
and are therefore interpreted as integer bytes. And you want to interpret them as IEEE-754 floating point bytes, you can use the package for that: unsafe
f := *(*float32)(unsafe.Pointer(&n2)) fmt.Println(f)
Conclusion (try it on the Go Playground ):
-561.2863
Notes:
As JimB pointed out, for the second part (translation uint32
into float32
) the package has a built-in function that does it exactly under the hood: math
math.Float32frombits()
f := math.Float32frombits(n2)
source to share
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
}
source to share
The input is 32 bits, so it should be treated as a 32 bit number. It is also unsigned, so it should be parsed as a uint, not an int. Finally, there is no need to use unsafe operations, and in fact, as they are used here, they will fail on a machine with a different byte order.
Instead, use math.Float32frombits
one that 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
source to share