35

I'm trying to convert a []uint8 byte slice into a float64 in GoLang. I can't find a solution for this issue online. I've seen suggestions of converting to a string first and then to a float64 but this doesn't seem to work, it loses it's value and I end up with zeroes.

Example:

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

And it doesn't work...

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
user3435186
  • 361
  • 1
  • 3
  • 4

4 Answers4

67

For example,

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

Output:

[24 45 68 84 251 33 9 64]
3.141592653589793
peterSO
  • 158,998
  • 31
  • 281
  • 276
  • Odd that you defaulted to little endian. Network byte order is on the internet more and... ma asked sense. – Dustin Mar 19 '14 at 07:13
  • This was it except we're using BigEndian. Thanks sir! – user3435186 Mar 19 '14 at 13:40
  • 2
    Little endian is nearly universal these days. Even modern network protocols use it (which makes sense - virtually all processors are little endian so you'd just be swapping bytes at both ends pointlessly). – Timmmm Jul 25 '17 at 09:43
6

I think this example from Go documentation is what you are looking for: 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)

Prints 3.141592653589793

Kluyg
  • 5,119
  • 2
  • 25
  • 28
  • 1
    This pretty much does exactly what the accepted answer does under the hood when inspecting the source code for binary.Read FYI – Eli Davis Jan 31 '23 at 19:07
6

As the comments read, it all depends on what kind of data you have in your []uint8 slice.

If it is bytes representing an IEEE 754 floating-point value in Little Endian order, then use Kluyg's or peterSo's (better performance without use of reflection) answer.

If it is a textual representation in Latin-1/UTF-8 encoding, then you should be able to do what you just did:

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

Result:

1.23

Playground: http://play.golang.org/p/-7iKRDG_ZM

I159
  • 29,741
  • 31
  • 97
  • 132
ANisus
  • 74,460
  • 29
  • 162
  • 158
2

I hope this hack helps. The purpose of it is to convert the long stream of binary numbers to float.

For example: 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
}
  • Please be more clear when posting code, posting a code and an example isn't enough sometimes, please edit your answer with more explanation. – eyadMhanna Jul 26 '16 at 10:50
  • 2
    I will amend it accordingly. This is my first post on StackOverflow. Sorry for not complying with the regulations in StackOverflow. – Mobieus Jay Jul 27 '16 at 00:48