将一个十六进制数转换为二进制,并能够访问每个位。

huangapple go评论79阅读模式
英文:

Convert a hexadecimal number to binary in Go and be able to access each bit

问题

我目前正在研究Go语言,并遇到了一个问题,我想得到一些反馈和帮助 将一个十六进制数转换为二进制,并能够访问每个位。

我的问题是,我有一个包含十六进制值的字符串作为输入,例如:

"60A100"

现在,我想将其转换为该数字的二进制表示,并能够查看特定位。

我目前的解决方案是:

i, err := strconv.ParseUint(rawHex, 16, 32)
if err != nil {
    fmt.Printf("%s", err)
}

// 将整数转换为二进制表示
// %024b 表示基数为2,使用0填充,共24个字符。
bin := fmt.Sprintf("%024b", i)

变量bin现在正好包含我想要的内容,但它是一个字符串,我认为这不是最优的。我更希望能够有一个包含各个位的数组,这样我就可以通过选择索引i来获取第i位的值 将一个十六进制数转换为二进制,并能够访问每个位。

因为据我目前所知,如果我像这样查找索引8;bin[8],我将得到一个对应于二进制数在ASCII表中的十进制值。

我已经搜索了很多,但我找不到完全符合要求的解决方案,也许我在错误的地方寻找。

希望你们能够指导我找到正确/最优的解决方案 将一个十六进制数转换为二进制,并能够访问每个位。

提前感谢!

英文:

I am fiddling around with Go at the moment and have stumpled upon a problem where I want to get some feedback and help 将一个十六进制数转换为二进制,并能够访问每个位。

My problem is that I have a string containing a hexadecimal value as input, such as this:

"60A100"

Now, I want to convert this to the binary representation of the number and be able to look at specific bits within.

My solution to this right now is:

i, err := strconv.ParseUint(rawHex, 16, 32)
if err != nil {
	fmt.Printf("%s", err)
}

// Convert int to binary representation
// %024b indicates base 2, padding with 0, with 24 characters.
bin := fmt.Sprintf("%024b", i)

The variable bin now holds exactly what I want, except it is a string which I don't think is optimal. I would rather that I could have an array of the individual bits such that I could just choose index i to get bit number i 将一个十六进制数转换为二进制,并能够访问每个位。

Because as far as I know right now, if I lookup index 8 like so; bin[8], I will get a decimal that corresponds to the binary number, in the ASCII table.

I have searched quite a bit, but I can't find a solution that fits perfectly, but maybe I am looking in the wrong spot.

I hope you guys can guide me to the correct / optimal solution in this case 将一个十六进制数转换为二进制,并能够访问每个位。

Thanks in advance!

答案1

得分: 2

在解析值之后,您可以直接访问每个位。您可以使用类似以下的代码:

func getNthBit(val, n uint32) int {
    n = 32 - n
    if 1 << n & val > 0 {
        return 1
    }
    return 0
}

这段代码可以用来获取给定值 val 的第 n 位。

英文:

After parsing the value you can directly access each bit. You can use something like this:

func getNthBit(val, n uint32) int {
    n = 32 - n
    if 1 &lt;&lt; n &amp; val &gt; 0 {
        return 1
    }
    return 0
}

答案2

得分: 2

你可以将其转换为表示位的切片。

// 这也可以返回 []bool
func asBits(val uint64) []uint64 {
    bits := []uint64{}
    for i := 0; i < 24; i++ {
        bits = append([]uint64{val & 0x1}, bits...)
        // 或者
        // bits = append(bits, val & 0x1)
        // 取决于你想要的顺序
        val = val >> 1
    }
    return bits
}

func main() {
    rawHex := "60A100"
    i, err := strconv.ParseUint(rawHex, 16, 32)
    if err != nil {
        fmt.Printf("%s", err)
    }
    fmt.Printf("%024b\n", i)

    fmt.Println(asBits(i))

}

输出

011000001010000100000000
[0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0]

https://play.golang.org/p/KK_AUPgbZu

正如 @jimb 指出的那样,你也可以检查单个位。

fmt.Printf("第9位是否设置?%t\n", (i >> 8) & 1 == 1)

这就是 @n-carter 的答案所做的。

英文:

You could turn it into a slice representing bits

// This could also return []bool
func asBits(val uint64) []uint64 {
	bits := []uint64{}
	for i := 0; i &lt; 24; i++ {
		bits = append([]uint64{val &amp; 0x1}, bits...)
		// or
		// bits = append(bits, val &amp; 0x1)
        // depending on the order you want
		val = val &gt;&gt; 1
	}
	return bits
}

func main() {
	rawHex := &quot;60A100&quot;
	i, err := strconv.ParseUint(rawHex, 16, 32)
	if err != nil {
		fmt.Printf(&quot;%s&quot;, err)
	}
	fmt.Printf(&quot;%024b\n&quot;, i)

	fmt.Println(asBits(i))

}

OUTPUT

011000001010000100000000
[0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0]

https://play.golang.org/p/KK_AUPgbZu

As @jimb points out, you can also just check an individual bit

fmt.Printf(&quot;9th bit is set? %t\n&quot;, (i &gt;&gt; 8) &amp; 1 == 1)

which is what @n-carter's answer does.

答案3

得分: 2

根据 @n-carter 的回答,你可以单独访问每个位。

有两种方法:

选项1:移动 value

将二进制数向右移动 n 位,以获取第 n 位。然后与 1 进行掩码操作。

func getNthBit(val, n uint32) int {
    // 1. 反转 golang 的字节序
    nthBit := 32-n
    // 2. 将第 n 位移动到第一位
    movedVal := val >> nthBit
    // 3. 对值进行掩码操作,只选择第一位
    maskedValue := movedVal & 1
    return maskedValue
    // 可以简写为
    // return (val >> (32-n)) & 1
}

解释:

1. 根据字节序获取正确的位索引
01100000101000010000000001000101
  ^
(32-3)=29 位

2. 移动位,将第 n 位移动到第一位
01100000101000010000000001000101 >> 29
^^^
00000000000000000000000000000011
                             ^^^

3. 对第一位进行掩码操作,提取该位的值
00000000000000000000000000000011
&                              ^
00000000000000000000000000000001
                               1

选项2:移动 1 并与之进行掩码操作

这可以像 @n-carter 所做的那样完成。将 1 向左移动。

func getNthBit(val, n uint32) int {
    // 1. 反转 golang 的字节序
    nthBit := 32-n
    // 2. 将掩码 1 位移动到第 n 位
    mask := 1 << nthBit
    // 3. 对值进行掩码操作,只选择第 n 位
    maskedValue := val & mask
    if maskedValue == 0 {
        return 0
    }
    return 1
    // 可以简写为:
    // if val & (1 << (32-n)) == 0 {
    //     return 0
    // }
    // return 1

}

解释:

1. 根据字节序获取正确的位索引
01100000101000010000000001000101
  ^
(32-3)=29 位

2. 将 1 移动到第 n 位 (1 << 29 == 2^(29-1))
00000000000000000000000000000001 << 29
00100000000000000000000000000000

3. 对第 n 位进行掩码操作,提取该位的值
01100000101000010000000001000101
&
00100000000000000000000000000000
  1

希望对你有所帮助。在脑海中可视化位操作可能需要一些时间。

英文:

Following @n-carter answer, you can access each bit individually

There are two approaches:

Option 1: Shifting the value:

Shift the bin number to the right n possitions to get the n-th bit the first one. then mask it with 1

func getNthBit(val, n uint32) int {
    // 1. reverse the golang endian
    nthBit := 32-n
    // 2. move the nth bit to the first position
    movedVal := val &gt;&gt; nthBit
    // 3. mask the value, selecting only this first bit
    maskedValue := movedVal &amp; 1
    return maskedValue
    // can be shortened like so
    // return (val &gt;&gt; (32-n)) &amp; 1
}

Explanation:

1. Get the right bit index according to the endian
01100000101000010000000001000101
  ^
(32-3)=29nth bit

2. Shift the bits to get n-th in the first possition
01100000101000010000000001000101 &gt;&gt; 29
^^^
00000000000000000000000000000011
                             ^^^

3. Mask first bit. This picks(extracts) the value from this bit
00000000000000000000000000000011
&amp;                              ^
00000000000000000000000000000001
                               1

Option 2: shifting 1 and masking with it

This can be done the way @n-carter does. Shift a 1 to the left

func getNthBit(val, n uint32) int {
    // 1. reverse the golang endian
    nthBit := 32-n
    // 2. move the mask 1 bit to the nth position
    mask := 1 &lt;&lt; nthBit
    // 3. mask the value, selecting only this nth bit
    maskedValue := val &amp; mask
    if maskedValue == 0 {
        return 0
    }
    return 1
    // can be written shorter like:
    //if val &amp; (1 &lt;&lt; (32-n)) == 0 {
    //    return 0
    //}
    //return 1

}

Explanation:

1. Get the right bit index according to the endian
01100000101000010000000001000101
  ^
(32-3)=29nth bit

2. Shift the 1 to the n-th position (1 &lt;&lt; 29 == 2^(29-1))
00000000000000000000000000000001 &lt;&lt; 29
00100000000000000000000000000000

3. Mask n-th bit. This picks(extracts) the value from this bit
01100000101000010000000001000101
&amp;
00100000000000000000000000000000
  1

Hope this helps. It takes some time to visualise bit operations in your head.

huangapple
  • 本文由 发表于 2017年3月24日 23:40:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/43003700.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定