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