Python:将numpy符号数组转换为int和b

2024-09-30 16:30:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图从一个numpy符号数组(即一个numpy数组,其条目是1.或{})转换为整数,然后通过二进制表示返回。我有一些有用的东西,但它不是Python,我希望它会很慢。在

def sign2int(s):
    s[s==-1.] = 0.
    bstr = ''
    for i in range(len(s)):
        bstr = bstr + str(int(s[i]))
    return int(bstr, 2)

def int2sign(i, m):
    bstr = bin(i)[2:].zfill(m)
    s = []
    for d in bstr:
        s.append(float(d))
    s = np.array(s)
    s[s==0.] = -1.
    return s

那么

^{pr2}$

我关心的是(1)每个中的for循环和(2)必须构建一个作为字符串的中间表示。在

最终,我也会想要一个能与二维numpy数组一起工作的东西——例如

>>> s = np.array([[1., -1., 1.], [1., 1., 1.]])
>>> print sign2int(s)
[5, 7]

Tags: innumpyforreturndefnp二进制符号
3条回答

以下是一些函数的矢量化版本:

def sign2int(s):
    return int(''.join(np.where(s == -1., 0, s).astype(int).astype(str)), 2)

def int2sign(i, m):
    tmp = np.array(list(bin(i)[2:].zfill(m)))
    return np.where(tmp == "0", "-1", tmp).astype(int)

s0 = np.array([1., -1., 1., 1.])

sign2int(s0)
# 11

int2sign(11, 5)
# array([-1,  1, -1,  1,  1])

要在二维数组上使用函数,可以使用map函数:

^{pr2}$

对于1d数组,可以使用这种一种线性数乘方法,使用np.packbits

>>> np.packbits(np.pad((s0+1).astype(bool).astype(int), (8-s0.size, 0), 'constant'))
array([11], dtype=uint8)

对于倒车:

^{pr2}$

对于二维阵列:

>>> x, y = s.shape
>>> np.packbits(np.pad((s+1).astype(bool).astype(int), (8-y, 0), 'constant')[-2:])
array([5, 7], dtype=uint8)

对于倒车:

>>> unpack = (np.unpackbits(np.array([5, 7], dtype='uint8'))).astype(float).reshape(x, 8)[:,-y:]
>>> unpack[unpack==0] = -1
>>> unpack
array([[ 1., -1.,  1.],
       [ 1.,  1.,  1.]])

我先从sig2int。。从符号表示转换为二进制

>>> a
array([ 1., -1.,  1., -1.])
>>> (a + 1) / 2
array([ 1.,  0.,  1.,  0.])
>>> 

然后你可以简单地创建一个2的幂的数组,乘以二进制数,然后求和。在

^{pr2}$

然后通过添加轴信息并依赖广播使其对行进行操作。在

def sign2int(a):
    # powers of two
    powers = np.arange(a.shape[-1])[::-1]
    np.power(2, powers, powers)
    # sign to "binary" - add one and divide by two
    np.add(a, 1, a)
    np.divide(a, 2, a)
    # scale by powers of two and sum
    np.multiply(a, powers, a)
    return np.sum(a, axis = -1)
>>> b = np.array([a, a, a, a, a])
>>> sign2int(b)
array([ 11.,  11.,  11.,  11.,  11.])
>>> 

我在一个4乘100位的数组上尝试过,它看起来很快

>>> a = a.repeat(100)
>>> b = np.array([a, a, a, a, a])
>>> b
array([[ 1.,  1.,  1., ...,  1.,  1.,  1.],
       [ 1.,  1.,  1., ...,  1.,  1.,  1.],
       [ 1.,  1.,  1., ...,  1.,  1.,  1.],
       [ 1.,  1.,  1., ...,  1.,  1.,  1.],
       [ 1.,  1.,  1., ...,  1.,  1.,  1.]])
>>> sign2int(b)
array([  2.58224988e+120,   2.58224988e+120,   2.58224988e+120,
         2.58224988e+120,   2.58224988e+120])
>>> 

如果我能想到的话,我会加上相反的。-我所能做的最好的方法就是使用一些没有任何numpy向量化魔法的纯Python,除了一次迭代并转换一个int之外,我还不知道如何使它与一系列int一起工作,但是时间似乎还是可以接受的。在

def foo(n):
    '''yields bits in increasing powers of two

    bit sequence from lsb --> msb
    '''
    while n > 0:
        n, r = divmod(n, 2)
        yield r

def int2sign(n):
    n = int(n)
    a = np.fromiter(foo(n), dtype = np.int8, count = n.bit_length())
    np.multiply(a, 2, a)
    np.subtract(a, 1, a)
    return a[::-1]

1324工程:

>>> bin(1324)
'0b10100101100'
>>> a = int2sign(1324)
>>> a
array([ 1, -1,  1, -1, -1,  1, -1,  1,  1, -1, -1], dtype=int8)

似乎适用于1.2e305:

>>> n = int(1.2e305)
>>> n.bit_length()
1014
>>> a = int2sign(n)
>>> a.shape
(1014,)

>>> s = bin(n)
>>> s = s[2:]
>>> all(2 * int(x) -1 == y for x, y in zip(s, a))
True
>>>

相关问题 更多 >