使用合适的填充将整数转换为二进制数组

时间:2014-03-06 14:37:34

标签: python numpy

我在0..2**m - 1范围内有整数,我想将它们转换为长度为m的二进制numpy数组。例如,说m = 4。现在15 = 1111为二进制,因此输出应为(1,1,1,1)。二进制2 = 10,因此输出应为(0,0,1,0)。如果m3,则2应转换为(0,1,0)

我尝试了np.unpackbits(np.uint8(num)),但这并没有给出正确长度的数组。例如,

np.unpackbits(np.uint8(15))
Out[5]: array([0, 0, 0, 0, 1, 1, 1, 1], dtype=uint8)

我想要一种适用于代码中m {。}}的方法。

3 个答案:

答案 0 :(得分:11)

您应该能够对此进行矢量化,例如

>>> d = np.array([1,2,3,4,5])
>>> m = 8
>>> (((d[:,None] & (1 << np.arange(m)))) > 0).astype(int)
array([[1, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0, 0],
       [1, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0],
       [1, 0, 1, 0, 0, 0, 0, 0]])

只获取适当的位权重,然后按位和:

>>> (1 << np.arange(m))
array([  1,   2,   4,   8,  16,  32,  64, 128])
>>> d[:,None] & (1 << np.arange(m))
array([[1, 0, 0, 0, 0, 0, 0, 0],
       [0, 2, 0, 0, 0, 0, 0, 0],
       [1, 2, 0, 0, 0, 0, 0, 0],
       [0, 0, 4, 0, 0, 0, 0, 0],
       [1, 0, 4, 0, 0, 0, 0, 0]])

有很多方法可以将它转换为1,无论它是非零(> 0)*1.astype(bool).astype(int)等等。我基本上随机选择了一个。

答案 1 :(得分:0)

这是一个有点'hacky'的解决方案。

def bin_array(num, m):
    """Returns an array representing the binary representation of num in m bits."""
    bytes = int(math.ceil(m / 8.0))
    num_arr = np.arange(num, num+1, dtype='>i%d' %(bytes))
    return np.unpackbits(num_arr.view(np.uint8))[-1*m:]     

答案 2 :(得分:0)

好像你可以修改生成的数组。我不完全知道这个函数,但像np.unpackbits这样的大多数实现本身并不知道数字的大小 - 毕竟python int可以任意大,并且没有原生大小。

但是,如果您知道m,则可以轻松“修复”数组。基本上,解包函数将为数字中具有最高1的字节提供一些位数(即8的倍数)。您只需要删除额外的0或前置0,以获得正确的距离:

m = 4
mval = np.unpackbits(np.uint8(15))

if len(mval) > m:
   mval = mval[m-len(mval):]
elif m > len(mval):
   # Create an extra array, and extend it
   mval = numpy.concatenate([numpy.array([0]*(m-len(mval)), dtype=uint8), mval])