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

      

+5


source to share


3 answers


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)

      

+7


source


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
}

      

+6


source


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

      

http://play.golang.org/p/y1ZjH9pscy

0


source







All Articles