在Go语言中将字节切片"[]uint8" 转换为float64

35

我正尝试将 Go 语言中的 []uint8 字节片转换为 float64。目前在网上找不到解决方案。有人建议先将其转换为字符串,然后再转换为 float64,但这似乎行不通,数值会变成零。

示例:

metric.Value, _ = strconv.ParseFloat(string(column.Value), 64)

它不起作用...


1
字节数组包含什么? - cnicutar
1
发布一个数据示例的例子。 - Nick Craig-Wood
4
如果你意外地得到了零值,并且忽略了返回的错误,请检查一下这个错误,也许这是值得做的。 - James Henstridge
顺便说一下,我遇到了同样的问题(在转换后得到了0),我的问题是在[]byte中有一个空格/行终止符字符(在将%s转储到stdout时不可见),所以我用strconv.ParseFloat(strings.TrimSpace(string(b)), 64)修复了它。 - Karl Pokus
4个回答

68
例如,
package main

import (
    "encoding/binary"
    "fmt"
    "math"
)

func Float64frombytes(bytes []byte) float64 {
    bits := binary.LittleEndian.Uint64(bytes)
    float := math.Float64frombits(bits)
    return float
}

func Float64bytes(float float64) []byte {
    bits := math.Float64bits(float)
    bytes := make([]byte, 8)
    binary.LittleEndian.PutUint64(bytes, bits)
    return bytes
}

func main() {
    bytes := Float64bytes(math.Pi)
    fmt.Println(bytes)
    float := Float64frombytes(bytes)
    fmt.Println(float)
}

输出:

[24 45 68 84 251 33 9 64]
3.141592653589793

有点奇怪,你默认使用小端字节序。网络字节序在互联网上更为常见,这是有道理的。 - Dustin
这就是它,除了我们使用BigEndian。谢谢先生! - user3435186
2
现在几乎所有的系统都采用小端序。即使是现代网络协议也使用它(这很有道理 - 几乎所有处理器都是小端序,因此你只会毫无意义地在两端交换字节)。 - Timmmm

7
我认为这个来自Go文档的例子是你所寻找的: http://golang.org/pkg/encoding/binary/#example_Read
var pi float64
b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
buf := bytes.NewReader(b)
err := binary.Read(buf, binary.LittleEndian, &pi)
if err != nil {
  fmt.Println("binary.Read failed:", err)
}
fmt.Print(pi)

打印出 3.141592653589793


1
这基本上在检查二进制读取源代码时与被接受的答案做的一样。FYI - Eli Davis

6
根据评论所述,一切取决于您在[]uint8 切片中拥有哪种类型的数据。
如果这些字节表示按小端序排列的IEEE 754浮点值,则使用Kluyg或peterSo的答案(无需使用反射可获得更好的性能)。
如果这是Latin-1 / UTF-8编码的文本表示,则您应该能够执行刚才所做的操作:
package main

import (
    "fmt"
    "strconv"
)

func main() {
    var f float64
    text := []uint8("1.23") // A decimal value represented as Latin-1 text

    f, err := strconv.ParseFloat(string(text), 64)
    if err != nil {
        panic(err)
    }

    fmt.Println(f)
}

结果:

1.23

实验场: http://play.golang.org/p/-7iKRDG_ZM


2
我希望这种方法能有所帮助。它的目的是将长串的二进制数转换为浮点数。
例如: 0110111100010010100000111100000011001010001000010000100111000000 -> -3.1415
func binFloat(bin string) float64 {

    var s1 []byte
    var result float64

    if len(bin) % 8 == 0 {

            for i := 0; i < len(bin) / 8; i++ {

                    //Chop the strings into a segment with a length of 8.
                    //Convert the string to Integer and to byte

                    num, _ := strconv.ParseInt(bin[8*i: 8*(i + 1)], 2, 64) 
                    //Store the byte into a slice s1
                    s1 = append(s1, byte(num)) 
            }

    }

    //convert the byte slice to a float64. 
    //The algorithm below are copied from golang binary examples. 

    buf := bytes.NewReader(s1)

    //You can also change binary.LittleEndian to binary.BigEndian
    //For the details of Endianness, please google Endianness

    err := binary.Read(buf, binary.LittleEndian, &result) 

    if err != nil {

            panic(err)
            fmt.Println("Length of the binary is not in the length of 8")
    }

    return result
}

请在发布代码时更加清晰明了,有时仅仅发布代码和示例是不够的,请编辑您的答案并添加更多解释。 - eyadMhanna
2
这是我在StackOverflow上的第一篇帖子。很抱歉没有遵守StackOverflow的规定,我会相应地进行修改。 - Mobieus Jay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接