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

huangapple go评论121阅读模式
英文:

How to convert hex to float

问题

我需要将以字符串形式表示的十六进制数(例如"0xC40C5253")转换为浮点数值(IEEE-754转换)。我尝试使用strconv.ParseFloat函数进行转换,但没有成功。我还尝试先将其转换为整数,然后再转换为浮点数,但结果是错误的。

以下是我最后一次尝试的代码:

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. func main() {
  7. x, err := strconv.ParseInt("C40C5253", 16, 64)
  8. f, err := strconv.ParseFloat(fmt.Sprintf("%d", x), 64)
  9. if err != nil {
  10. fmt.Printf("转换错误:%s\n", err)
  11. } else {
  12. fmt.Println(f)
  13. }
  14. }

请问有其他方法可以实现这个转换吗?

英文:

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:

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. func main () {
  7. x, err := strconv.ParseInt("C40C5253", 16, 64)
  8. f, err := strconv.ParseFloat(fmt.Sprintf("%d", x), 64)
  9. if err != nil {
  10. fmt.Printf("Error in conversion: %s\n", err)
  11. } else {
  12. fmt.Println(f)
  13. }
  14. }

答案1

得分: 10

首先需要说明输入的位长度。由于十六进制表示有4个字节(8个十六进制数字),很可能是float32(需要向提问者澄清)。

您可以使用strconv.ParseUint()将十六进制表示中的字节解析为uint32ParseUint()始终返回uint64,它在内存中使用8个字节,因此您需要将其转换为与float32一样使用4个字节的uint32

  1. s := "C40C5253"
  2. n, err := strconv.ParseUint(s, 16, 32)
  3. if err != nil {
  4. panic(err)
  5. }
  6. n2 := uint32(n)

现在,您已经获得了字节,但它们存储在uint32类型的变量中,因此被解释为整数的字节。如果您想将它们解释为IEEE-754浮点数的字节,可以使用unsafe包来实现:

  1. import (
  2. "fmt"
  3. "unsafe"
  4. )
  5. f := *(*float32)(unsafe.Pointer(&n2))
  6. fmt.Println(f)

输出结果(在Go Playground上尝试):

  1. -561.2863

注意:

正如JimB指出的,对于第二部分(将uint32转换为float32),math包中有一个内置函数math.Float32frombits()可以在底层执行此操作:

  1. import "math"
  2. f := math.Float32frombits(n2)
英文:

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:

  1. s := "C40C5253"
  2. n, err := strconv.ParseUint(s, 16, 32)
  3. if err != nil {
  4. panic(err)
  5. }
  6. 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:

  1. f := *(*float32)(unsafe.Pointer(&n2))
  2. fmt.Println(f)

Output (try it on the Go Playground):

  1. -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:

  1. f := math.Float32frombits(n2)

答案2

得分: 6

这里有两种不同的方法可以得到-561.2863:http://play.golang.org/p/Y60XB820Ib

  1. import (
  2. "bytes"
  3. "encoding/binary"
  4. "encoding/hex"
  5. "math"
  6. "strconv"
  7. )
  8. func parse_read(s string) (f float32, err error) {
  9. b, err := hex.DecodeString(s)
  10. if err != nil {
  11. return
  12. }
  13. buf := bytes.NewReader(b)
  14. err = binary.Read(buf, binary.BigEndian, &f)
  15. return
  16. }
  17. func parse_math(s string) (f float32, err error) {
  18. i, err := strconv.ParseUint(s, 16, 32)
  19. if err != nil {
  20. return
  21. }
  22. f = math.Float32frombits(uint32(i))
  23. return
  24. }
英文:

Here are two different approaches that produce -561.2863: http://play.golang.org/p/Y60XB820Ib

  1. import (
  2. "bytes"
  3. "encoding/binary"
  4. "encoding/hex"
  5. "math"
  6. "strconv"
  7. )
  8. func parse_read(s string) (f float32, err error) {
  9. b, err := hex.DecodeString(s)
  10. if err != nil {
  11. return
  12. }
  13. buf := bytes.NewReader(b)
  14. err = binary.Read(buf, binary.BigEndian, &f)
  15. return
  16. }
  17. func parse_math(s string) (f float32, err error) {
  18. i, err := strconv.ParseUint(s, 16, 32)
  19. if err != nil {
  20. return
  21. }
  22. f = math.Float32frombits(uint32(i))
  23. return
  24. }

答案3

得分: 1

输入是32位的,因此必须将其视为32位数字。它还是无符号的,因此应该解析为uint而不是int。最后,没有必要使用不安全的操作,实际上,在这里使用它们将在具有不同字节顺序的机器上失败。

相反,使用math.Float32frombits,它正好可以满足你的需求:

  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. "strconv"
  6. )
  7. func main() {
  8. s := "C40C5253"
  9. n, err := strconv.ParseUint(s, 16, 32)
  10. if err != nil {
  11. panic(err)
  12. }
  13. nn := uint32(n)
  14. g := math.Float32frombits(nn)
  15. fmt.Println(g)
  16. }

输出:

  1. -561.2863

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

英文:

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:

  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. "strconv"
  6. )
  7. func main() {
  8. s := "C40C5253"
  9. n, err := strconv.ParseUint(s, 16, 32)
  10. if err != nil {
  11. panic(err)
  12. }
  13. nn := uint32(n)
  14. g := math.Float32frombits(nn)
  15. fmt.Println(g)
  16. }

Output:

  1. -561.2863

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

huangapple
  • 本文由 发表于 2015年5月28日 23:20:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/30510711.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定