2015-07-28 91 views
3

我一直在寻找一个程序中的错误,我发现它是由来自numpy的一个意想不到的行为产生...意外NumPy的/ Py3k强制规则

在做,例如,在不同的一个简单的算术运算使用Python3k和numpy的,像

整数类型

(numpy.uint64)+(int)的

结果是...一个numpy.float64

下面是一个例子:

v = numpy.array([10**16+1], dtype=numpy.uint64) 
print(v[0]) 
v[0] += 1 
print(v[0]) 

它产生如下结果:

10000000000000001 
10000000000000000 

这是相当意外的,当你用整数处理,以避免舍入误差...

上述“问题”可以很容易地解决通过numpy.uint64(1)替换1,但我可以看到许多错误来自这个。这种情况背后的规则和逻辑是什么?有没有关于在这种情况下强制执行的方式的文档?我找不到它。

我之前还以为你可以通过使用.item()对强制转换的一些见解,但它更误导:

v = numpy.array([10**16+1], dtype=numpy.uint64) 
print(type(v[0].item())) 
v[0] = v[0].item() + 1 
print(v[0]) 

产生

<class 'int'> 
10000000000000001 
10000000000000002 

所以.item()变换numpy.uint64转换为int,如果你明确地在算术运算中使用它,它就可以工作。

我很惊讶,(但我缺乏经验numpy的,我猜),即,当 'A' 对应于一个特定的numpy的D类,

a.item() + 1 

a + 1 

不产生相同的结果......并因此在转换回numpy dtype时给出不同的结果。我通常使用Python 2,但是我必须在Py3k中做一些测试,而且这是一个方便的方法来做到这一点。 。它)

+0

它正常工作与'D型= np.int64'代替'D型= np.uint64'(均为蟒2和3,numpy的1.6和1.9)。我真的不明白为什么会这样,听起来像一个bug ...只要使用'np.int64',没有理由使用'uint64',在'2⁶4 - 1'或'2⁶³ - 1'处溢出。对于所有的实际目的来说都是一样的。 – rth

+1

这很有趣...确实,它适用于'dtype = np.int64' ...不知道它是否是一个错误(尽管它看起来像一个bug),因为'np.int32 + int'和'np .uint32 + int'都转换为'np.int64',可能会避免溢出。为什么'np.int64 + int'变成'np.int64','np.uint64 + int'变成'np.float64'仍然没有效果。我已经有很多解决方法,但我想知道是否有这个原因,以及我能在哪里找到它。感谢您的评论... – Koren

+0

这里是相应的[numpy问题](https://github.com/numpy/numpy/issues/5745),这使得在某些层次的敏感,但它仍然不是很直观。 – rth

回答

0

正如上面指出:

它工作正常:

dtype=np.int64 

代替:

dtype=np.uint64 

python 2和3,numpy 1.6和1.9。

只需使用:

np.int64 

没有理由使用uint64,在2⁶⁴ - 12⁶³ - 1四溢几乎是所有的实际目的是一样的。

参考

+0

我坚决不同意,它对于所有实际目的都是一样的...... 在处理二进制数据时,我经常需要精确的整数类型。问题是旧的,但我认为我当时需要它(我已经明确地使用它之前和之后)。用int64,你会有比较问题,并警告溢出。 这就是说,这只是一个意想不到的隐式转换选择,而且很容易规避,所以这不是一个真正的问题,但我认为它应该在numpy文档中更明显。并不是说没有充足的情况下,numpy文档远非完美:/ – Koren