当前位置: 首页 > Linux

Python的整数和Numpy的数据溢出

时间:2023-04-06 19:04:28 Linux

有同学A给我发截图,问为什么结果里面有负数?看图,我的第一感觉就是数据溢出了。如果数据超过了可以表示的最大值,就会出现奇怪的结果。然后,他继续发了一张图片,内容是print(100000*208378),就是直接打印上图中的E[0]*G[0],结果是20837800000,是正确的结果。那么新的问题是:如果上图中的数据溢出了,为什么直接相乘的数没有溢出呢?由于我一直忽略了数据表示规则(整数的上限是多少?),而且我对Numpy了解不多,所以也看错了图中的结果,误以为每条数据都是错误的,所以我无法回答。最后经过学习组的一番讨论,终于明白是怎么回事了,所以这篇文章整理了相关的知识点。在正式开始之前,先总结一下上图会引出的话题:Python3中整数的上限是多少?Python2呢?Numpy中整数的上限是多少?出现整数溢出怎么办?关于第一个问题,先看Python2,它有两种整数:一种是短整型,也就是常说的整型,用int表示,内置函数int()。它的大小是有限的,可以通过sys.maxint()查看(取决于平台是32位还是64位)。一种是长整型,即大小不限的整数,用long表示,内置函数long()。写法是在数字后加大写字母L或小写l,如1000L。当整数超出短整数的范围时,会自动用长整数表示。例如,打印2**100将在结果末尾附加字母L以指示它是一个长整数。但是到了Python3,情况就不一样了:它只有一个内置的整数,表示为int,形式上是Python2中的短整型,但实际上可以表示无限范围,表现得更像一个长整数。无论数字有多大,末尾都不需要字母L来区分。也就是说,Python3整合了两种整数表示,用户不再需要自己区分,交给底层按需处理。理论上,Python3中的整数没有上限(只要它们不超过内存空间)。这就解释了为什么我们在上一篇文章中直接打印两个数的乘积结果是正确的。PEP-237(统一长整数和整数)中描述了这种转换。它解释了这样做的目的:这将使新的Python程序员(无论他们是否是编程新手)在开始之前少学一项功课。Python在语言应用层屏蔽了很多琐碎的工作,比如内存分配,所以我们不用担心使用字符串、列表或字典等对象。整数类型的转换也是为了这样方便的目的。(缺点是牺牲了一些效率,这里就不说了)回到上面的第二个话题:Numpy中整数的上限是多少?由于是用C语言实现的,所以整数表示采用C语言的规则,即区分整数和长整数。有一种方法可以查看:importnumpyasnpa=np.arange(2)type(a[0])#结果:numpy.int32表示它的默认整型int是32位,表示范围是-2147483648~2147483647.对比之前的截图,只有两组数相乘没有溢出:100007*4549、100012*13264,其他数据组都溢出了,所以出现了奇怪的负数结果。Numpy比Python支持更多的数据类型,它们之间的界限是多种多样的:截图来源:https://www.runoob.com/numpy/numpy-dtype.html要解决整数溢出的问题,可以指定dtype方法:importnumpyasnpq=[100000]w=[500000]#溢出的例子:a=np.array(q)b=np.array(w)print(a*b)#产生溢出,结果是a奇怪的值#一个解决的例子:c=np.array(q,dtype='int64')d=np.array(w,dtype='int64')print(c*d)#没有溢出:[50000000000]好是的,前面提出的问题得到了回答。让我们结束吧:Python3极大地简化了整数的表示。效果可以表示为:整数只有一种整数(int),没有其他类型的整数(long、int8、int64等)Numpy中的整数类型对应于数据类型C语言。每个“整数”都有自己的区间。要解决数据溢出的问题,需要指定更大的数据类型(dtype)(dtype),有喵星哲学猫系列、Python进阶系列、好书推荐系列、技术写作、优质英文推荐与翻译等,欢迎关注。