Skip to main content
 首页 » 编程设计

python之为什么移动 numpy uint8 会产生负值

2024年08月28日28TianFang

我在 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'> 

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

请您参考如下方法:

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'