如何将十六进制转换为浮点数
How to convert hex to float
我必须将 hex
表示为 string
s(例如 "0xC40C5253"
)转换为浮点值(IEEE-754 转换) .我没有设法使用 strconv.ParseFloat 函数来做到这一点。还有什么我必须使用的吗?
到目前为止我找不到它。我也试过先转整数再转浮点数,但是结果不对。
我最后一次尝试的代码:
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)
}
}
首先需要说明输入的位长。由于十六进制表示有 4 个字节(8 个十六进制数字),它很可能是 float32
(需要提问者的说明)。
您可以使用 strconv.ParseUint()
将十六进制表示中的字节解析为 uint32
。 ParseUint()
always returns uint64
在内存中使用 8 个字节,因此您必须将其转换为 uint32
,它使用 4 个字节,就像 float32
:
s := "C40C5253"
n, err := strconv.ParseUint(s, 16, 32)
if err != nil {
panic(err)
}
n2 = uint32(n)
现在您有了字节,但它们存储在 uint32
类型的变量中,因此被解释为整数的字节。你想将它们解释为 IEEE-754 浮点数的字节,你可以使用 unsafe
包来做到这一点:
f := *(*float32)(unsafe.Pointer(&n2))
fmt.Println(f)
输出(在 Go Playground 上尝试):
-561.2863
注:
正如 JimB 指出的那样,对于第二部分(将 uint32
翻译成 float32
),math
package has a built-in function math.Float32frombits()
正是在幕后执行此操作:
f := math.Float32frombits(n2)
输入是 32 位,因此必须被视为 32 位数字。它也是无符号的,所以应该被解析为一个 uint,而不是 int。最后,没有必要使用不安全的操作,事实上,正如这里所使用的那样,它们在具有不同字节顺序的机器上会失败。
相反,使用 math.Float32frombits
,它完全符合您的要求:
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)
}
输出:
-561.2863
这里有两种产生 -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
}
我必须将 hex
表示为 string
s(例如 "0xC40C5253"
)转换为浮点值(IEEE-754 转换) .我没有设法使用 strconv.ParseFloat 函数来做到这一点。还有什么我必须使用的吗?
到目前为止我找不到它。我也试过先转整数再转浮点数,但是结果不对。
我最后一次尝试的代码:
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)
}
}
首先需要说明输入的位长。由于十六进制表示有 4 个字节(8 个十六进制数字),它很可能是 float32
(需要提问者的说明)。
您可以使用 strconv.ParseUint()
将十六进制表示中的字节解析为 uint32
。 ParseUint()
always returns uint64
在内存中使用 8 个字节,因此您必须将其转换为 uint32
,它使用 4 个字节,就像 float32
:
s := "C40C5253"
n, err := strconv.ParseUint(s, 16, 32)
if err != nil {
panic(err)
}
n2 = uint32(n)
现在您有了字节,但它们存储在 uint32
类型的变量中,因此被解释为整数的字节。你想将它们解释为 IEEE-754 浮点数的字节,你可以使用 unsafe
包来做到这一点:
f := *(*float32)(unsafe.Pointer(&n2))
fmt.Println(f)
输出(在 Go Playground 上尝试):
-561.2863
注:
正如 JimB 指出的那样,对于第二部分(将 uint32
翻译成 float32
),math
package has a built-in function math.Float32frombits()
正是在幕后执行此操作:
f := math.Float32frombits(n2)
输入是 32 位,因此必须被视为 32 位数字。它也是无符号的,所以应该被解析为一个 uint,而不是 int。最后,没有必要使用不安全的操作,事实上,正如这里所使用的那样,它们在具有不同字节顺序的机器上会失败。
相反,使用 math.Float32frombits
,它完全符合您的要求:
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)
}
输出:
-561.2863
这里有两种产生 -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
}