为啥移动 numpy uint8 会产生负值?

Posted

技术标签:

【中文标题】为啥移动 numpy uint8 会产生负值?【英文标题】:Why does shifting a numpy uint8 create negative values?为什么移动 numpy uint8 会产生负值? 【发布时间】:2014-02-06 21:08:33 【问题描述】:

我在 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】:

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'

【讨论】:

以上是关于为啥移动 numpy uint8 会产生负值?的主要内容,如果未能解决你的问题,请参考以下文章

如果输入是numpy数组,为啥scikit-learns Multiple Regression方法会产生错误?

nasm idiv 负值

为啥这些随机数会慢慢趋向负值?

matlab 为啥要进行数据类型转换?

hfss 增益为啥会出现负值

为啥 c++ 线程是可移动的但不可复制的?