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

时间:2014-02-06 21:08:34

标签: python numpy

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

我确信没有人会对此感到惊讶:

>>> n = 0x94 << 24
>>> n
2483027968L
>>> hex(n)
'0x94000000L'

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

>>> n = np.uint8(0x94) << 24
>>> n
-1811939328
>>> hex(n)
'-0x6c000000'

有人会认为显式无符号类型更不可能返回负值。

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

>>> n = np.uint8(0x74) << 24
>>> n; hex(n)
1946157056
'0x74000000'

我碰巧注意到numpy似乎是将无符号类型提升为签名类型:

>>> n = np.uint8(0x74) << 24
>>> type(n)
<type 'numpy.int32'>

这似乎是一个明显的错误。我找不到这种已知错误的引用,但是......是吗?

1 个答案:

答案 0 :(得分:3)

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

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

>>> np.uint8(0x94) << 56
-7782220156096217088
>>> type(np.uint8(0x94) << 56)
<type 'numpy.int64'>

将右手参数设为无符号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'