学习日记
numpy是一个python的科学计算库,库如其名,(num)number的简写,(py)python嘛(我是这么理解的)。numpy里面内置了许多数学运算,以及数据类型。
前几天学习基因遗传算法的时候,我瞟了一眼网上的源码,诸位神级人物都是用minpy计算库来计算的,这个库需要安装mxnet框架才能用。秉承着同样功能的包只装一个的懒人情怀。我决定用numpy去做数学计算,不用minpy。
然后,我就差点废了。我是在计算match_rate += np.sum(np.abs(im[i] - im2[i]))
这么一个语句的时候发生了溢出。我是要比对两张图片的相似情况,最直接的办法就是,把这两张图的每一个像素的rgb颜色组成分别做差,求平方在求和得到一个值(rate),用这个rate来衡量两张图片像不像。我们知道如果两张图片一样的话,那对应的像素点做差肯定是0(因为图片一样嘛)。之后,平方,求和肯定也是0。故rate越小两个图片越像。rate=0,那就是同一张图!
这个rate是一张图片每一个像素点的rgb三个属性与另一张图相应的rgb属性做差平方之后求和得到的,这个数是很大的(大约11位数往上),已经超出了int32所能储存的最大数字。numpy在计算过程中用什么数据类型存储数字,完全取决于,你调用这个方法时,传入的数字是什么类型。例如a = np.sum([12345678]*256)
这个句子中,12345678是可以用32位的int数表示的,所以结果a的数据类型就是int32位!但是12345678*256肯定超出了int32的存储范围,所以a 这个结果一定会溢出
就像这样12345678 * 256 = -1134473728 明显不对嘛。
解决方案
其实解决方案也简单,要想算出正确的结果,我们只需要传入参数是指定好数据类型,告诉numpy这是一个64位的整数,不要用32位存它,这样子就可以了。例如:a =np.sum([np.int64(12345678)]*256)
我指定12345678是一个64位的数。这样结果就不会发生溢出了。
这里有一个坑,就是我这样指定行不行np.int64(np.sum([12345678]*256))
不是计算结果溢出了吗,我把计算结果指定成64位数。按道理,也解决了吧。实际是不行的,因为这个时候,np检查到你设置64位数的时候已经把计算结果算出来了。
科普
32位数就是用32个二进制位存储一个整数,其中第一位是符号位,0,表示整数,1表示负数。剩下的31位就用来存储这个数了。所以说,32int能存的最大数,2的31次方-1,为啥减一,是因为我们是从0开始数的。
64位那也就同理了。