0
votes

I have a slice of int containing only zeros and ones ([]int{1,1,1,1,0,0,0,0})

I want to convert the string representation to hex value. I'm converting the slice of ints to a slice of strings then doing a strconv.ParseUint to convert.

package main

import (
    "fmt"
    "log"
    "strconv"
    "strings"
)

func IntToString(values []int) string {
    valuesText := []string{}
    for i := range values {
        valuesText = append(valuesText, strconv.Itoa(values[i]))
    }
    return strings.Join(valuesText, "")
}

func IntSliceToHex(in []int) (string, error) {
    intString := IntToString(in)
    ui, err := strconv.ParseUint(intString, 2, 64)
    if err != nil {
        return "", err
    }
    return fmt.Sprintf("%X", ui), nil
}

func HexToBin(hex string) (string, error) {
    ui, err := strconv.ParseUint(hex, 16, 64)
    if err != nil {
        return "", err
    }
    return fmt.Sprintf("%b", ui), nil
}

func main() {
    profile := []int{1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1}

    hex, err := IntSliceToHex(profile)
    if err != nil {
        log.Fatalln(err)
    }

    bin, err := HexToBin(hex)
    if err != nil {
        log.Fatalln(err)
    }

    fmt.Println(hex, bin)
}

OUTPUT: F0F 111100001111

Is there a better way to do this?

1

1 Answers

5
votes

You should use bitshift operations to build up the actual number from the slice rather than converting each bit to string and parsing it.

You should also keep the built-up integer rather than converting back and forth to a string.

package main

import (
    "fmt"
)

func main() {
    profile := []int{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

    final := uint64(profile[0])
    for i := 1; i < len(profile); i++ {
        final <<= 1
        final += uint64(profile[i])
    }
    fmt.Printf("%X %b\n", final, final)
    // Output: FFFFFFFFFFFF0000 1111111111111111111111111111111111111111111111110000000000000000
}

Note: final is an unsigned 64 bit integer and can handle profile slices of length up to (and including) 64. For larger sizes, use big.Int.