#go #slice
#Вперед #фрагмент
Вопрос:
У меня есть фрагмент int, содержащий только нули и единицы ( []int{1,1,1,1,0,0,0,0}
)
Я хочу преобразовать строковое представление в шестнадцатеричное значение. Я конвертирую фрагмент целых чисел в фрагмент строк, а затем выполняю strconv.ParseUint
преобразование.
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)
}
ВЫВОД: F0F 111100001111
Есть ли лучший способ сделать это?
Ответ №1:
Вы должны использовать операции сдвига битов для создания фактического числа из фрагмента, а не преобразовывать каждый бит в строку и анализировать его.
Вы также должны сохранить созданное целое число, а не преобразовывать туда и обратно в строку.
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 %bn", final, final)
// Output: FFFFFFFFFFFF0000 1111111111111111111111111111111111111111111111110000000000000000
}
Примечание: final
является 64-разрядным целым числом без знака и может обрабатывать profile
фрагменты длиной до 64 (включительно). Для больших размеров используйте big.Int.
Комментарии:
1. Вау, это довольно аккуратно! Я не слишком знаком с операциями сдвига битов, поэтому мне придется прочитать об этом. В моем примере был сокращен фрагмент целых чисел. В моем случае это был бы фрагмент из 64 целых чисел. Я получаю совершенно другой результат. профиль:= []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} Вывод: -10000 -10000000000000000
2. Подправил пример кода. С 64 битами это 64-битное целое число без знака. Если у вас есть больше, вам нужно будет использовать что-то другое (например, big.Int )