【问题标题】:Numpy bitwise xor on signed int有符号整数上的 Numpy 按位异或
【发布时间】:2021-01-20 14:01:43
【问题描述】:

我正在读取一些偏移二进制格式的二进制数据。 numpy 中的有符号整数是二进制补码,因此值不正确。要修复数据,我需要翻转最重要的位。但是,我从按位异或得到了一些意想不到的结果,并且不完全确定发生了什么。

例子:

data = np.array([1, 7, -1, -8], dtype='i1')
mask = 0b10000000

def print_bin(data, out):
    for d, o in zip(data, out):
        bin_data =np.binary_repr(d, d.dtype.itemsize*8)
        bin_out = np.binary_repr(o, o.dtype.itemsize*8)
        print(f'{bin_data} to {bin_out}')
        
print_bin(data, data ^ mask)

输出:

00000001 to 0000000010000001
00000111 to 0000000010000111
11111111 to 1111111101111111
11111000 to 1111111101111000

似乎numpy 可能在 xor 之前进行某种类型的转换,因为输出是 16 位整数。如果我使用函数形式 np.bitwise_xor 而不是 ^ 我会得到相同的结果。有趣的是,如果我用-mask 进行异或运算,结果是正确的。或者,如果我以函数形式指定 dtype。

print_bin(data, np.bitwise_xor(data, mask, dtype='i1'))
print_bin(data, data ^ -mask)

输出:

00000001 to 10000001
00000111 to 10000111
11111111 to 01111111
11111000 to 01111000

谁能准确解释第一种情况发生了什么?

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    您的mask = 0b10000000 是一个无符号整数表示:

    >>> mask
    ... 128
    

    这需要 16 位来表示为有符号整数,因此 numpy 将所有整数转换为 16 位以适应此操作。您正在寻找具有二进制表示 '10000000' 的有符号整数。这对应于整数-128

    所以mask = -128 应该可以解决您的问题!这也是为什么否定掩码有效的原因 (-mask = -128 = '10000000' as a signed int.

    将掩码转换为 int8 numpy 整数也可以解决问题:

    >>> np.array(0b10000000, dtype='i1')
    ... array(-128, dtype=int8)
    

    【讨论】:

    • 这是有道理的。我假设 numpy 应该只知道我想要我设置的二进制表示形式的掩码。但是,我想由于 Python 并没有真正的无符号类型,因此 numpy 无法确切知道我的意思。我有点惊讶,如果我将掩码定义为array(128, dtype='u1'),它仍然会出错。我认为 numpy 会足够聪明,可以看到位宽相同并使用view 执行按位运算。
    • 是的,我同意这有点令人惊讶。我想这与如何处理由无符号整数和有符号整数组成的操作的一些定义有关。您可以只获取位值并将其转换为无符号或有符号(但此处可能存在歧义)。或者您将带符号的 int 转换为无符号表示(这将涉及使用更多位)...... Numpy 显然选择了后者或这两个选项。知道这是否是处理问题的标准方法会很有趣
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多