web-dev-qa-db-fra.com

Convertir le tableau d'octets "[] uint8" en float64 dans GoLang

J'essaie de convertir un []uint8 tableau d'octets dans un float64 dans GoLang. Je ne trouve pas de solution à ce problème en ligne. J'ai vu des suggestions de conversion en chaîne d'abord, puis en float64 mais cela ne semble pas fonctionner, il perd sa valeur et je me retrouve avec des zéros.

Exemple:

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

Et ça ne marche pas ...

24
user3435186

Par exemple,

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)
}

Production:

[24 45 68 84 251 33 9 64]
3.141592653589793
50
peterSO

Comme le lisent les commentaires, tout dépend du type de données que vous avez dans votre []uint8 tranche.

S'il s'agit d'octets représentant une valeur à virgule flottante IEEE 754 dans l'ordre Little Endian, utilisez la réponse de Kluyg ou de peterSo (meilleure performance sans utilisation de la réflexion).

S'il s'agit d'une représentation textuelle en encodage Latin-1/UTF-8, alors vous devriez pouvoir faire ce que vous venez de faire:

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)
}

Résultat:

1,23

Aire de jeux: http://play.golang.org/p/-7iKRDG_ZM

4
ANisus

Je pense que cet exemple de la documentation Go est ce que vous recherchez: 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)

Impressions 3.141592653589793

4
Kluyg

J'espère que ce hack vous aidera. Le but est de convertir le long flux de nombres binaires en flottant.

Par exemple: 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
}
2
Mobieus Jay