2014-04-27 31 views
2

所以我一直创造numpy的阵列那样:当我为给定的dtype设置的值太大时会发生什么?

>>> u = np.zeros(10, int) 
>>> v = np.zeros(10, float) 

我一直无视有关最大允许值,直到如今。我一直认为它会简单地工作。如果没有,我会得到OverflowError,然后我会找到一些解决方法,如采取对数。

但最近我开始使用其他dtypes:

>>> v8 = np.zeros(10, np.uint8) 
>>> v8[0] = 2 ** 8 - 1 
>>> v8[1] = 2 ** 8 
>>> v8 
>>> array([255, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=uint8) 

好了,所以当我分配比255这是一个有点吓人更大的价值我没有得到任何警告。

所以我的问题是:

  • 当我使用类型intfloat阵列,是有可能,我设置的值过大(导致完全错误的计算)不知道呢?
  • 如果我想使用uint8,我必须手动检查所有分配的值是否在[ 0, 255 ]

回答

0

是,UINT8会掩盖你的价值观(带8 LSB),所以你需要手动检查:

>>> a = numpy.uint8(256) 
>>> a 
0 

是的,你没有意识到它可能会发生溢出。这是许多编程语言的常见错误来源。但是,python中的长整型以不同寻常的方式运行:它们没有明确定义的限制。

我已经在this answer中写过。

1

numpy在机器层面非常深入。测试很耗时,所以测试由开发人员完成。 Python更高级并且许多测试都是自动完成的,或者对于int,int可以具有任意大的值。无处不在你需要在速度和安全之间做出决定。在速度方面,numpy更远。

在需要测试值范围的情况下,您必须自行检查。

- 方法可以帮助你:

>>> u = np.array([124,-130, 213]) 
>>> u.astype('b') 
array([124, 126, -43], dtype=int8) 
>>> u.clip(-128,127).astype('b') 
array([ 124, -128, 127], dtype=int8) 
1

正如在其他的答案解释,过大型值“缠”,所以你需要手工剪裁他们的最小值和最大值转换前允许的值。对于整数,这些限制可以使用np.iinfo获得。你可以写你自己的效用函数做这个转换以安全的方式对一个给定的D型:

def safe_convert(x, new_dtype): 
    info = np.iinfo(new_dtype) 
    return x.clip(info.min, info.max).astype(new_dtype) 

快速测试:

In [31]: safe_convert(np.array([-1,0,1,254,255,256]), np.uint8) 
Out[31]: array([ 0, 0, 1, 254, 255, 255], dtype=uint8) 

In [32]: safe_convert(np.array([-129,-128,-127,126,127,128]), np.int8) 
Out[32]: array([-128, -128, -127, 126, 127, 127], dtype=int8) 
0

如前所述,numpy的环绕避免做检查。

如果裁剪不可接受,那么在投射之前,您可以使用numpy.min_scalar_type来获取将保留数据而不丢失数据的最小dtype。

另外请注意,实际上使用uint8的唯一理由是将存储器保存在非常大的阵列中,因为计算速度通常大致相同(在某些操作中将内部向上流动,甚至是向上流动)。如果你的阵列不是太大以至于内存不是一个大问题,你应该更安全,并且使用uint16甚至uint32来进行中间计算。如果内存是你的问题,你应该考虑移出核心存储,比如PyTables;如果您现在即将填满内存,也许使用更大的数据集即使uint8也不足够。

相关问题