How to convert hex to float

14,661

Solution 1

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)

Solution 2

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
}

Solution 3

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

Share:
14,661
Jan
Author by

Jan

Updated on June 25, 2022

Comments

  • Jan
    Jan almost 2 years

    I have to convert hex, represeneted as strings (e.g. "0xC40C5253") to float values (IEEE-754 conversion). I did not manage to do that using the strconv.ParseFloat function. Is there anything else I have to use? I couldn't find it so far. I also tried converting it to an integer first and then to a float, but the results were wrong.

    Code of my last try:

    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)
      }
    }