首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >numpy将int解析为位分组

numpy将int解析为位分组
EN

Stack Overflow用户
提问于 2014-12-29 23:07:40
回答 2查看 1.2K关注 0票数 3

我有一个np.array of np.uint8

代码语言:javascript
复制
a = np.array([randint(1,255) for _ in range(100)],dtype=np.uint8)

我想把它分成低的和高的两部分

我可以吃点小东西

代码语言:javascript
复制
low = np.bitwise_and(a,0xF)

我就能吃到一口

代码语言:javascript
复制
high = np.bitwise_and(np.right_shift(a,4),0xF)

有什么办法可以像

代码语言:javascript
复制
>>> numpy.keep_bits(a,[(0,3),(4,7)])
numpy.array([
  [low1,high1],
  [low2,high2],
  ...
  [lowN,highN]
  ])

我甚至不确定这会叫什么..。但我想,也许一些矮胖的古鲁知道一个很酷的方法(实际上,我想用uint32 32和更多不同的小吃来做这件事。)

基本上类似于struct.unpack,但用于向量化的numpy操作。

编辑:我使用了下面接受的答案的修改版本

这是我给有兴趣的人的最后代码

代码语言:javascript
复制
def bitmask(start,end):
    """
    >>> bitmask(0,2) == 0b111
    >>> bitmask(3,5) == 0b111000

    :param start: start bit 
    :param end:  end bit (unlike range, end bit is inclusive)
    :return: integer bitmask for the specified bit pattern
    """
    return (2**(end+1-start)-1)<<start

def mask_and_shift(a,mask_a,shift_a):
    """

    :param a: np.array 
    :param mask_a: array of masks to apply (must be same size as shift_a)
    :param shift_a: array of shifts to apply (must be same size as mask_a)
    :return: reshaped a, that has masks and shifts applied
    """
    masked_a = numpy.bitwise_and(a.reshape(-1,1), mask_a)
    return numpy.right_shift(masked_a,shift_a)

def bit_partition(rawValues,bit_groups):
    """
    >>> a = numpy.array([1,15,16,17,125,126,127,128,129,254,255])
    >>> bit_partition(a,[(0,2),(3,7)])
    >>> bit_partition(a,[(0,2),(3,5),(6,7)])

    :param rawValues: np.array of raw values
    :param bit_groups: list of start_bit,end_bit values for where to bit twiddle
    :return: np.array len(rawValues)xlen(bit_groups)
    """
    masks,shifts = zip(*[(bitmask(s,e),s) for s,e in bit_groups])
    return mask_and_shift(rawValues,masks,shifts)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-29 23:32:03

一种使用广播的单线线,用于四比特下位和上咬口:

代码语言:javascript
复制
In [38]: a
Out[38]: array([  1,  15,  16,  17, 127, 128, 255], dtype=uint8)

In [39]: (a.reshape(-1,1) & np.array([0xF, 0xF0], dtype=np.uint8)) >> np.array([0, 4], dtype=np.uint8)
Out[39]: 
array([[ 1,  0],
       [15,  0],
       [ 0,  1],
       [ 1,  1],
       [15,  7],
       [ 0,  8],
       [15, 15]], dtype=uint8)

要概括这一点,请将硬编码值[0xF, 0xF0][0, 4]替换为适当的位掩码和移位。例如,要将值拆分为三个组,其中包含最高的两个位,其次是三个位的其余两个组,您可以这样做:

代码语言:javascript
复制
In [41]: masks = np.array([0b11000000, 0b00111000, 0b00000111], dtype=np.uint8)

In [42]: shifts = np.array([6, 3, 0], dtype=np.uint8)

In [43]: a
Out[43]: array([  1,  15,  16,  17, 127, 128, 255], dtype=uint8)

In [44]: (a.reshape(-1,1) & np.array(masks, dtype=np.uint8)) >> np.array(shifts, dtype=np.uint8)
Out[44]: 
array([[0, 0, 1],
       [0, 1, 7],
       [0, 2, 0],
       [0, 2, 1],
       [1, 7, 7],
       [2, 0, 0],
       [3, 7, 7]], dtype=uint8)
票数 4
EN

Stack Overflow用户

发布于 2014-12-29 23:27:46

所以,我不会评论您想要实现的特定的逻辑操作符,因为位黑客并不是我的专长,但是我可以告诉您在numpy中应该在哪里实现这种自定义操作符。

如果您查看numpy源代码,您会注意到numpy中几乎所有的比特流提升技术都只是_MaskedBinaryOperation的实例,例如,bitwise_and的定义就是:

代码语言:javascript
复制
bitwise_and = _MaskedBinaryOperation(umath.bitwise_and)

这里的神奇之处在于umath模块的形式,它调用numpy所依赖的低级库。如果你真的想的话,你可以把你的操作员加在那里,但我不认为在那个层次上混混是值得的。

尽管如此,这并不是将这些函数合并到numpy中的唯一方法。实际上,umath模块有一个非常方便的函数,名为frompyfunc,它允许您将任意的python函数转换为这些方便的umath操作符之一。文档可以找到这里。下面是创建这样一个函数的一个例子:

代码语言:javascript
复制
>>> oct_array = np.frompyfunc(oct, 1, 1)
>>> oct_array(np.array((10, 30, 100)))
array([012, 036, 0144], dtype=object)
>>> np.array((oct(10), oct(30), oct(100))) # for comparison
array(['012', '036', '0144'],
      dtype='|S4')

如果您决定要实现的按位运算符的细节,使用此接口将是实现它的最佳方法。

这不能百分之百地回答您的问题,但我认为您的问题更多的是以适当的numpy形式实现一些自定义的位运算符,而不是深入到位运算符本身。如果这是不准确的,请告诉我,我可以用上面提到的按位运算符组合一个例子。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27697340

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档