Ответ 1
Хотя это не задокументировано, 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)),
)
<класс 'int'> <класс 'numpy.int64'> <класс 'numpy.int64'> <класс 'numpy.int64'> int64 <класс 'numpy.int64'> <класс 'numpy.int64'>
Первый использует собственный тип int
Python, а все остальные преобразуются в numpy.int64
, где поведение для 32-битного сдвига является правильным. В основном это связано с тем, что скалярные (нульмерные) массивы ведут себя по-разному. И в случае list
что целочисленный тип по умолчанию для numpy не numpy.uint32
.
С другой стороны
print((np.array([2**31], dtype=np.uint32) >> 32).dtype)
uint32
Таким образом, вы столкнулись с неопределенным поведением здесь.