2016-10-28 2 views
2

Я пытаюсь вычислить расстояние Хэмминга между двумя байтами, такими, чтоКак получить бит из байта в golang?

HammingDist(byte(255), byte(0)) == 8

мне нужен биты в каждом байте, но я не могу найти какую-либо функции в любом из встроенных пакетов для этого. Итак, учитывая byte(1), как мне получить бит-представление 00000001?

+0

Вы можете использовать BitReader как в https://play.golang.org/p/Wyr_K9YAro – dmitryro

ответ

5

Вы можете видеть визуальное представление бит с использованием fmt.Sprintf(%08b, ..), как уже указывали другие.

Однако, если вы хотите использовать биты в операциях, например, для вычисления расстояния Хэмминга, вам необходимо использовать bitwise operators.

Для вычисления п-й бит байта, вы должны будете bitwise AND, что байт с другой байт которого энный бит установлен в 1, а остальные до 0 (ака маскировка). Другими словами, этот другой байт (маска) представляет собой номер 2^n-1.

Например, чтобы найти 1-й бит числа 13 (00001101), мы должны были бы замаскировать его 2^0 = 1 (00000001). Мы сравниваем результат выполнения побитового И на обоих числах с маской. Если они равны, это означает, что n-й бит равен 1, иначе оно равно 0. Мы продолжаем так и находим все биты. Иллюстрированный в Go Код:

fmt.Print(13 & 1) // Output: 1 -> 1 
fmt.Print(13 & 2) // Output: 0 -> 0 
fmt.Print(13 & 4) // Output: 4 -> 1 
fmt.Print(13 & 8) // Output: 8 -> 1 
// Not necessary to continue, but shown for the sake of the example 
fmt.Print(13 & 16) // Output: 0 -> 0 
fmt.Print(13 & 32) // Output: 0 -> 0 
fmt.Print(13 & 64) // Output: 0 -> 0 
fmt.Print(13 & 128) // Output: 0 -> 0 

Таким образом, 13 в двоичной системе является 00001101

Вот функция, которую я недавно написал для вычисления расстояния Хемминга между двумя массивами байтов. Просто передать массив, состоящий из одного байта каждого в вашем случае

func hamming(a, b []byte) (int, error) { 
    if len(a) != len(b) { 
     return 0, errors.New("a b are not the same length") 
    } 

    diff := 0 
    for i := 0; i < len(a); i++ { 
     b1 := a[i] 
     b2 := b[i] 
     for j := 0; j < 8; j++ { 
      mask := byte(1 << uint(j)) 
      if (b1 & mask) != (b2 & mask) { 
       diff++ 
      } 
     } 
    } 
    return diff, nil 
} 

Go Экспозиция: https://play.golang.org/p/O1EGdzDYAn

+0

из любопытства, вы знаете, почему '% b' только показывает только 6 бит? – Matt

3

fmt.Sprintf ("% 08b", byte (1)) - отличная идея. Он показывает вам, как число хранится внутри. И пример для вычисления расстояния Хэмминга (очень скучный) может быть:

package main 

import (
    "fmt" 
) 

func HamDist(n1,n2 uint8) uint8 { 
    var w uint8 = 0 
    if n1&1 != n2&1 { 
     w++ 
    } 
    if n1&2 != n2&2 { 
     w++ 
    } 
    if n1&4 != n2&4 { 
     w++ 
    } 
    if n1&8 != n2&8 { 
     w++ 
    } 
    if n1&16 != n2&16 { 
     w++ 
    } 
    if n1&32 != n2&32 { 
     w++ 
    } 
    if n1&64 != n2&64 { 
     w++ 
    } 
    if n1&128 != n2&128 { 
     w++ 
    } 
    return w 
} 

func main() { 
    fmt.Println(HamDist(255,0)) 
} 

И теперь задачи для вас:

  1. переписать код с использованием цикла
  2. расширить программу для вычисления расстояния Хэмминга от 16- разрядный номер
  3. , пожалуйста, подумайте, что делает оператор xor и не следует ли вычислить HammingDistance проще, если вы определили функцию, которая вычисляет вес Хэмминга.
+0

Очень хороший ответ , воспитывая вместо того, чтобы раздавать прямое решение. Так держать! – janos

Смежные вопросы