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

问题描述 投票:14回答:1

我的问题是

np.array([2**31], dtype=np.uint32) >> 32

不返回0,而是返回array([2147483648], dtype=uint32)。同样如此

np.right_shift(np.array([2**31], dtype=np.uint32), 32)

(所以我相信这简直就是如何实施>>)。

有趣的是,所有这些替代方案似乎都按预期工作,返回某种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),
)

特别是,代表2147483648[2147483648]的Numpy数组有什么不同?

我在JavaScript(Why does << 32 not result in 0 in javascript?)和C ++(Weird behavior of right shift operator (1 >> 32)Why is `int >> 32` not always zero?)中看到过这个问题,但还没有在Python / Numpy中看到过。事实上,Python和Numpy文档似乎都没有记录这种行为:

python arrays numpy bit-shift
1个回答
8
投票

虽然没有记录,但numpy主要用C实现,C(和C ++)中的移位运算符没有定义大于或等于位数的移位。所以结果可以是任意的。

如果您查看有效的示例类型,您将看到它们的工作原理:

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)),
)

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

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

另一方面

print((np.array([2**31], dtype=np.uint32) >> 32).dtype)

UINT32

所以你在这里遇到了未定义的行为。

© www.soinside.com 2019 - 2024. All rights reserved.