在Python中获取二进制数的0和1的数量

4

我正在尝试解决一道二进制谜题,我的策略是将一个网格转换为0和1,并且我想确保每行都有相同数量的0和1。

有没有一种方法可以在不迭代数字的情况下计算数字中有多少个1和0?

目前我正在做的是:

def binary(num, length=4):
    return format(num, '#0{}b'.format(length + 2)).replace('0b', '')

n = binary(112, 8)
// '01110000'
and then
n.count('0')
n.count('1')

有没有更有效的计算(或数学)方法来做这件事情?
2个回答

6
你需要的是一个数字的汉明重量。在低级语言中,你可能会使用巧妙的寄存器内的SIMD技巧或库函数来计算它。在Python中,最短和最有效的方法是将其转换为二进制字符串并计算'1'的数量:
def ones(num):
    # Note that bin is a built-in
    return bin(num).count('1')

你可以通过将总位数减去ones(num)来得到零的数量。
def zeros(num, length):
    return length - ones(num)

演示:
>>> bin(17)
'0b10001'
>>> # leading 0b doesn't affect the number of 1s
>>> ones(17)
2
>>> zeros(17, length=6)
4

2
如果长度适中(比如小于20),你可以使用列表作为查找表。
只有在进行大量查找时才值得生成该列表,但在这种情况下似乎是必要的。
例如,对于一个16位的“0”计数表,请使用以下内容。
zeros = [format(n, '016b').count('0') for n in range(1<<16)]
ones = [format(n, '016b').count('1') for n in range(1<<16)]

在这台计算机上,生成20位仍然不到一秒钟。

编辑:这似乎稍微快了一些:

zeros = [20 - bin(n).count('1') for n in range(1<<20)]
ones = [bin(n).count('1') for n in range(1<<20)]

你能解释一下 range(1<<20) 吗?我不明白它生成了什么。 - piggyback
你不想从0到20范围内吗? - piggyback
1
range(1<<4) 会生成所有的四位数 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] 等等。 - John La Rooy
抱歉,我现在看到了 ;) - piggyback
不,我想生成一个包含1,048,576个项目的列表。 - John La Rooy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接