所以我总是创建那样的numpy数组:
>>> 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的值时,我不会收到任何警告。这有点可怕。
所以我的问题是:
int
和float
的数组时,是否有可能在不知情的情况下设置一个太大的值(导致完全错误的计算)? uint8
,是否必须手动检查[ 0, 255 ]
中所有已分配的值? 答案 0 :(得分:1)
在需要测试值范围的情况下,您必须自己检查。
剪辑 - 方法可以帮助您:
>>> 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 :(得分:1)
正如其他答案中所解释的那样,过大的值会被包裹起来,因此您需要在转换之前手动将它们剪切到最小和最大允许值。对于整数,可以使用np.iinfo获得这些限制。您可以编写自己的实用程序函数,以安全的方式对给定的dtype执行此转换:
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)
答案 2 :(得分:0)
是的,uint8将掩盖你的值(取8 lsb),所以你需要手动检查它:
>>> a = numpy.uint8(256)
>>> a
0
是的,如果没有你意识到,溢出就会发生。它是许多编程语言中常见的错误来源。但是,python中的长整数以不常见的方式运行:它们没有明确定义的限制。
我在this answer写过这篇文章。
答案 3 :(得分:0)
正如已经解释的那样,numpy包裹起来以避免做检查。
如果剪辑不可接受,则在投射之前,您可以使用numpy.min_scalar_type
获取保存数据的最小dtype而不会丢失数据。
另请注意,实际上使用uint8
的唯一原因是将内存保存在非常大的数组中,因为计算速度通常大致相同(在某些操作中,内部会向内转换,甚至)。如果您的阵列不是太大而内存不是一个大问题,那么您应该更安全并使用uint16
甚至uint32
进行中间计算。如果内存是你的问题,你应该考虑转移到核心存储,如PyTables;如果您现在要填补内存,可能使用更大的数据集,即使uint8也不够。