duanhe1903
duanhe1903
2015-05-28 15:20
浏览 311
已采纳

如何将十六进制转换为浮点数

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
", err)
  } else {
    fmt.Println(f)
  }
}

图片转代码服务由CSDN问答提供 功能建议

我必须转换 hex ,以 string s表示 (例如“ 0xC40C5253” )浮点值( IEEE-754 转换)。 我没有使用strconv.ParseFloat函数做到这一点。 还有什么我需要使用的吗? 我到目前为止找不到。 我还尝试先将其转换为整数,然后转换为浮点数,但结果是错误的。

我上次尝试的代码:

 < 代码>包main 
 
import(
“ fmt” 
“ strconv” 
)
 
func main(){
x,err:= strconv.ParseInt(“ C40C5253”,16,64)
f  ,err:= strconv.ParseFloat(fmt.Sprintf(“%d”,x),64)
 
如果err!= nil {
 fmt.Printf(“转换错误:%s 
”,err  )
} else {
 fmt.Println(f)
} 
} 
   
 
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • dongxiaofa6359
    dongxiaofa6359 2015-05-28 15:40
    已采纳

    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)
    
    点赞 评论
  • dongxiane0395
    dongxiane0395 2015-05-28 15:51

    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

    点赞 评论
  • duan1989643
    duan1989643 2015-05-28 15:58

    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
    }
    
    点赞 评论

相关推荐