为什么移位 numpy uint8 会产生负值?

jsp*_*cer 4 python numpy

我在 Windows 上使用 python 2.7、numpy 1.6.1、32 位。我正在编写一个函数,将一些数据打包到 32 位整数中,并根据常量值生成 C 源声明。在这样做的过程中,我发现 numpy 的 uint8 类型有一些奇怪的行为。

我敢肯定,看到这一点,没有人会感到惊讶:

>>> n = 0x94 << 24
>>> n
2483027968L
>>> hex(n)
'0x94000000L'
Run Code Online (Sandbox Code Playgroud)

但是对 numpy uint8 做同样的事情,你会得到令我惊讶的东西:

>>> n = np.uint8(0x94) << 24
>>> n
-1811939328
>>> hex(n)
'-0x6c000000'
Run Code Online (Sandbox Code Playgroud)

人们可能会认为显式无符号类型返回负值的可能性更小。

请注意,符号位清除的值按预期工作:

>>> n = np.uint8(0x74) << 24
>>> n; hex(n)
1946157056
'0x74000000'
Run Code Online (Sandbox Code Playgroud)

我碰巧注意到 numpy 似乎正在将无符号类型提升为有符号类型:

>>> n = np.uint8(0x74) << 24
>>> type(n)
<type 'numpy.int32'>
Run Code Online (Sandbox Code Playgroud)

这似乎是一个明显的错误。我找不到任何关于此类已知错误的参考,但是......是吗?

NPE*_*NPE 6

numpy似乎将右侧参数 ( 24) 视为本机宽度的有符号整数(int32在您的情况下,int64在我的情况下)。

看起来它们uint8被提升为相同的类型,并且移位的结果也是相同的类型:

>>> np.uint8(0x94) << 56
-7782220156096217088
>>> type(np.uint8(0x94) << 56)
<type 'numpy.int64'>
Run Code Online (Sandbox Code Playgroud)

将右侧参数变为无符号int会得到您期望的结果:

>>> np.uint8(0x94) << np.uint(56)
10664523917613334528
>>> type(np.uint8(0x94) << np.uint(56))
<type 'numpy.uint64'>
>>> hex(np.uint8(0x94) << np.uint(56))
'0x9400000000000000L'
Run Code Online (Sandbox Code Playgroud)