在Golang中如何统计一位有多少位?

时间:2017-08-05 09:10:30

标签: go

假设我有两个变量,只使用6位:

var a byte = 31  // 00011111
var b byte = 50  // 00110010

第一个(a)比b多一位,但b当然大于a因此无法使用a > b

为了实现我的需要,我做了一个循环:

func countOneBits(byt byte) int {
    var counter int
    var divider byte

    for divider = 32; divider >= 1; divider >>= 1 {
        if byt & divider == divider {
            counter++
        }

    }

    return counter
}

This works,我可以使用countOneBits(a) > countOneBits(b) ...

但我不认为这是这种情况的最佳解决方案,我不认为这需要一个循环因为它我就在这里。

有更好的替代方案(在性能方面)来计算6位中有多少1

4 个答案:

答案 0 :(得分:2)

鉴于输入是单个字节,可能是查找表是最好的选择...只需要256个字节,你得到像

这样的代码
var count = bitcount[input];

答案 1 :(得分:1)

鉴于此函数将在下一个Go版本(今年8月的1.9)中的包math/bits中可用,这里是32位整数的代码。

// OnesCount32 returns the number of one bits ("population count") in x.
func OnesCount32(x uint32) int {
    return int(pop8tab[x>>24] + pop8tab[x>>16&0xff] + pop8tab[x>>8&0xff] + pop8tab[x&0xff])
}

pop8tab的定义here。特别是你的问题:8位

func OnesCount8(x uint8) int {
    return int(pop8tab[x])
}

答案 2 :(得分:1)

也可以使用二进制运算来计数位。请参阅此bit twiddling hacks

func bitSetCount(v byte) byte {
    v = (v & 0x55) + ((v>>1) & 0x55)
    v = (v & 0x33) + ((v>>2) & 0x33)
    return (v + (v>>4)) & 0xF
}

你必须进行基准测试,看看它是否比最容易实现的查找表更快。

答案 3 :(得分:1)

有POPCNT golang版本:

https://github.com/tmthrgd/go-popcount