【问题标题】:Convert byte slice "[]uint8" to float64 in GoLang在 GoLang 中将字节切片“[]uint8”转换为 float64
【发布时间】:2014-03-18 21:57:12
【问题描述】:

我正在尝试将 []uint8 字节切片转换为 GoLang 中的 float64。我在网上找不到这个问题的解决方案。我已经看到了先转换为字符串然后再转换为 float64 的建议,但这似乎不起作用,它失去了它的价值,我最终得到了零。

例子:

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

而且它不起作用......

【问题讨论】:

  • 字节数组包含什么?
  • 发布数据示例
  • 如果您意外获得零值并忽略返回的错误,也许值得检查该错误?
  • FWIW 我遇到了同样的问题(转换后以 0 结束),我的问题是我的 [] 字节中有一个空格/行终止符(将 %s 转储到标准输出时不可见)所以我用strconv.ParseFloat(strings.TrimSpace(string(b)), 64)修复了它

标签: arrays go uint8t


【解决方案1】:

例如,

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

【讨论】:

  • 奇怪的是你默认使用小端。网络字节序在互联网上越来越多,而且……问得有道理。
  • 就是这样,除了我们使用的是 BigEndian。谢谢先生!
  • Little endian 现在几乎是通用的。即使是现代网络协议也使用它(这是有道理的——几乎所有处理器都是小端的,所以你只是在两端毫无意义地交换字节)。
【解决方案2】:

我认为 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

【讨论】:

    【解决方案3】:

    正如 cmets 所读取的,这完全取决于您的 []uint8 切片中的数据类型。

    如果是字节表示以 Little Endian 顺序排列的 IEEE 754 浮点值,则使用 Kluyg's 或 peterSo's(不使用反射的更好性能)答案。

    如果它是 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

    【讨论】:

      【解决方案4】:

      我希望这个 hack 有所帮助。它的目的是将二进制数的长流转换为浮点数。

      例如: 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
      }
      

      【讨论】:

      • 请在发布代码时更加清楚,发布代码和示例有时还不够,请编辑您的答案并提供更多解释。
      • 我会做相应的修改。这是我在 StackOverflow 上的第一篇文章。很抱歉没有遵守 StackOverflow 中的规定。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 2021-10-29
      • 2014-01-25
      • 2018-07-04
      • 1970-01-01
      • 2017-09-27
      • 1970-01-01
      相关资源
      最近更新 更多