为什么(2 ^ 31)>> 32不是0?

ber*_*ers 14 python arrays numpy bit-shift

我的问题是

np.array([2**31], dtype=np.uint32) >> 32
Run Code Online (Sandbox Code Playgroud)

不返回0,而是返回array([2147483648], dtype=uint32)。情况也是如此

np.right_shift(np.array([2**31], dtype=np.uint32), 32)
Run Code Online (Sandbox Code Playgroud)

(所以我相信这只是>>实现方式)。

有趣的是,所有这些替代方案似乎都能按预期工作,并返回了以下内容0

print(
    2**31 >> 32,
    np.uint32(2**31) >> 32,
    np.array(2**31, dtype=np.uint32) >> 32,
    np.right_shift(2**31, 32),
    np.right_shift([2**31], 32),
    np.right_shift(np.uint32(2**31), 32),
    np.right_shift(np.array(2**31, dtype=np.uint32), 32),
)
Run Code Online (Sandbox Code Playgroud)

特别是,代表2147483648和的Numpy数组之间有什么区别[2147483648]

我已经在JavaScript(为什么<< << 32在JavaScript中不会导致0?)和C ++(右移运算符(1 >> 32)的奇怪行为为什么'int >> 32`并不总是为零?)中看到这个问题。,但尚未在Python / Numpy中使用。实际上,Python和Numpy文档似乎都没有记录这种行为:

Joe*_*Joe 8

尽管没有记录,但numpy大多在C中实现,而C(和C ++)中的shift运算符未针对大于或等于位数的移位进行定义。因此结果可以是任意的。

如果查看有效示例的类型,您将了解它们为何起作用:

print(
    type(2**31 >> 32),
    type(np.uint32(2**31) >> 32),
    type(np.array(2**31, dtype=np.uint32) >> 32),
    type(np.right_shift(2**31, 32)),
    np.right_shift([2**31], 32).dtype,
    type(np.right_shift(np.uint32(2**31), 32)),
    type(np.right_shift(np.array(2**31, dtype=np.uint32), 32)),
)
Run Code Online (Sandbox Code Playgroud)

<class'int'> <class'numpy.int64'> <class'numpy.int64'> <class'numpy.int64'> int64 <class'numpy.int64'> <class'numpy.int64'>

第一个使用Python自己的int类型,而其他所有都转换为numpy.int64,其中32位移位的行为是正确的。这主要是由于标量(零维)数组的行为不同。并且在listnumpy的默认整数类型不是的情况下 numpy.uint32

另一方面

print((np.array([2**31], dtype=np.uint32) >> 32).dtype)
Run Code Online (Sandbox Code Playgroud)

uint32

因此,您在这里遇到了未定义的行为。

  • 由于type(np.uint32(2 ** 31))是numpy.int64,因此np.array(2 ** 31,dtype = np.uint32)&gt;&gt; 64将再次给出非零值。 (2认同)
  • @bers我认为这应该被视为NumPy中的错误,因此我已经[报告了](https://github.com/numpy/numpy/issues/13106)。 (2认同)