英文:
How to convert hex to float
问题
我需要将以字符串形式表示的十六进制数(例如"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("转换错误:%s\n", err)
} else {
fmt.Println(f)
}
}
请问有其他方法可以实现这个转换吗?
英文:
I have to convert hex
, represeneted as string
s (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)
}
}
答案1
得分: 10
首先需要说明输入的位长度。由于十六进制表示有4个字节(8个十六进制数字),很可能是float32
(需要向提问者澄清)。
您可以使用strconv.ParseUint()
将十六进制表示中的字节解析为uint32
。ParseUint()
始终返回uint64
,它在内存中使用8个字节,因此您需要将其转换为与float32
一样使用4个字节的uint32
:
s := "C40C5253"
n, err := strconv.ParseUint(s, 16, 32)
if err != nil {
panic(err)
}
n2 := uint32(n)
现在,您已经获得了字节,但它们存储在uint32
类型的变量中,因此被解释为整数的字节。如果您想将它们解释为IEEE-754浮点数的字节,可以使用unsafe
包来实现:
import (
"fmt"
"unsafe"
)
f := *(*float32)(unsafe.Pointer(&n2))
fmt.Println(f)
输出结果(在Go Playground上尝试):
-561.2863
注意:
正如JimB指出的,对于第二部分(将uint32
转换为float32
),math
包中有一个内置函数math.Float32frombits()
可以在底层执行此操作:
import "math"
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
:
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)
答案2
得分: 6
这里有两种不同的方法可以得到-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
}
英文:
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
}
答案3
得分: 1
输入是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
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:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论