【问题标题】:Numpy: check whether a bit is set to 1 or 0 in an array?Numpy:检查数组中的某个位是否设置为1或0?
【发布时间】:2015-02-06 12:37:43
【问题描述】:

假设如下:

bitstring = numpy.random.random_integers(0,2**32,size=8).astype(numpy.uint32)

如何找出 256 位中的哪一个被设置为 1?我有这个……但这太疯狂了,不是吗?

maximum = (2**32)-1
for checkbit in range (256):
    yes = bool(numpy.bitwise_and((2**checkbit)%maximum, bitstring[  (  (checkbit // maximum) + checkbit % maximum ) // 32  ] ) )
    print 'bit', checkbit, 'set to', yes, 'in string', (  (checkbit // maximum) + checkbit % maximum ) // 32

我相信答案可能非常简单,但谷歌根本没有帮助,this related question is referring only to bytes

由于我需要执行此操作数十亿次,我想知道是否有一种 Python 方法可以让它尽可能快地工作。

【问题讨论】:

  • "256 位中的哪一个设置为 1" 您使用的数字最多为 2**32,即 32 位。当您谈到 256 位时,我的印象更多的是您的意思是 8 位数字,最高可达 256(无符号)。你是什​​么意思?
  • 第一行代码......它是一个双字符串,它是一个具有 8 个位置的 uint32 数组......因此我的 256 位。
  • 啊,现在明白了。感谢您的澄清。

标签: python numpy bit-manipulation bit bitstring


【解决方案1】:

我不确定您是否要计算“1”位的数量或检查是否设置了特定位。

要检查,我想更简单的方法是:bool(n&(1<<b)),其中n 是被测试的数字,b 是位(从 0 开始)。

要计算“1”位的数量,我想没有什么比查找表更快的了。 例如,您可以使用 65k 的内存并将 256 位分成 16 组,每组 16 位。然后,在表格中查找计数器的值。

为了生成表格,您可以使用任何其他提到的方法。例如:

table = [bin(i).count('1') for i in xrange(1<<16)]

然后,要计算位数,您可以将表格中的值相加,例如:

n = 0x123456789123456789
cnt = 0
while n > 0:
    cnt += table[n%((1<<16)-1)]
    n >>= 16

如果你有足够的内存,你可以增加你的表。对于 32 位表,您将需要 4GB 内存。这是处理与内存消耗的经典权衡。

【讨论】:

  • 位移!当然!我会做一些性能基准测试...谢谢!
【解决方案2】:

您可以使用[np.unpackbits]1,尽管您首先必须将您的数组视为np.uint8,并注意弄清楚系统的字节序如何影响您获得的结果:

>>> np.unpackbits(bitstring.view(np.uint8))
array([1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1,
       1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0,
       0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1,
       1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0,
       1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
       1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0,
       1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1,
       0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1,
       1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0,
       0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0,
       0, 0, 0], dtype=uint8)

【讨论】:

  • 我会检查一下并进行一些基准测试。谢谢!
【解决方案3】:

您可以使用bin将python中的数字转换为二进制字符串

n = 4187390046
binary_str = bin(n)

产量

Out[7]: '0b11111001100101101000000001011110'

然后您可以在该字符串中找到 1 的所有索引,例如

def find_ones(s):
    return [i - 2 for i, bit in enumerate(s) if bit == '1']

因为二进制字符串有前导0b,你应该相应地调整值

【讨论】:

  • 谢谢。我会做一些性能基准测试,然后返回这里并提供一些结果。
猜你喜欢
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 2015-12-07
  • 2019-11-02
  • 2023-01-04
  • 1970-01-01
  • 2020-03-11
  • 2020-05-06
相关资源
最近更新 更多