如何从golang中的字节中获取位?

时间:2016-10-28 15:34:09

标签: go

我试图计算两个字节之间的汉明距离,这样

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

我需要每个字节中的位,但是我无法在任何内置包中找到任何功能。那么,给定byte(1)如何得到位表示00000001?

5 个答案:

答案 0 :(得分:11)

您可以使用fmt.Sprintf(%08b, ..)看到比特的直观表示,正如其他人已经建议的那样。

但是,如果要在操作中使用这些位,例如计算汉明距离,则需要使用https://regex101.com/r/wdgUFZ/2

要计算一个字节的第n位,你需要bitwise AND该字节与另一个字节的 nth 位设置为1而其余字节设置为0(也就是屏蔽) 。换句话说,其他字节(掩码)是数字 2 ^ n-1

例如,要查找数字13(00001101)的第1位,我们必须用2 ^ 0 = 1(00000001)对其进行掩码。我们将两个数字上执行按位AND的输出与掩码进行比较。如果它们相等,则意味着第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
}

去游乐场:bitwise operators

答案 1 :(得分:3)

fmt.Sprintf(&#34;%08b&#34;,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。

答案 2 :(得分:1)

您可以轻松地做到:

fmt.Printf("%08b", YourNumber)

您还可以使用%016b%032b或其他任何方法。

答案 3 :(得分:0)

import "math/bits"

bits.OnesCount8(byte(0) ^ byte(255))

答案 4 :(得分:0)

这里有一些很好的答案,但是计算两个字节之间的汉明距离的另一种方法是对它们进行异或并计算1的数量(权重)。计算我所知道的1的最简单方法是获得最后一位,方法是用1屏蔽它,然后右移。

这是我在golang中编写的用于计算两个字符串之间的汉明距离的函数。

func HammingDistance(s1, s2 string) (int, error) {
    if len(s1) != len(s2) {
        return 0, fmt.Errorf("Hamming distance of strings of different lengths %d and %d", len(s1), len(s2))
    }
    b1 := []byte(s1)
    b2 := []byte(s2)
    distance := 0
    for i := range b1 {
        xored := b1[i] ^ b2[i]
        for j := 0; j < 8; j++ {
            distance += int(xored & 1)
            xored = xored >> 1
        }
    }
    return distance, nil
}

要计算两个字节的汉明距离,只需要内部for循环。