python数据溢出怎么解决_Python整数与Numpy数据溢出问题
解决
某位 A 同学发了我⼀张截图,问为何结果中出现了负数?
看了图,我第⼀感觉就是数据溢出了。数据超出能表⽰的最⼤值,就会出现奇奇怪怪的结果。
然后,他继续发了张图,内容是 print(100000*208378),就是直接打印上图的 E[0]*G[0],结果是 20837800000,这是个正确的结果。
所以新的问题是:如果说上图的数据溢出了,为何直接相乘的数却没有溢出?
由于我⼀直忽视数据的表⽰规则(整型的上限是多少?),⽽且对 Numpy 了解不多,还错看了图中结果,误以为每⼀个数据都是错误的,所以就解答不出来。
最后,经过学习⾥的⼀番讨论,我才终于明⽩是怎么回事,所以本⽂把相关知识点做个梳理。
在正式开始之前,先总结⼀下上图会引出的话题:
Python 3 中整数的上限是多少?Python 2 呢?
Numpy 中整数的上限是多少?出现整数溢出该怎么办?编程先学c语言还是python
关于第⼀个问题,先看看 Python 2,它有两种整数:
⼀种是短整数,也即常说的整数,⽤ int 表⽰,有个内置函数 int()。其⼤⼩有限,可通过sys.maxint() 查看(取决于平台是 32 位还是 64位)
⼀种是长整数,即⼤⼩⽆限的整数,⽤ long 表⽰,有个内置函数 long()。写法上是在数字后⾯加⼤写字母 L 或⼩写的 l,如 1000L
当⼀个整数超出短整数范围时,它会⾃动采⽤长整数表⽰。举例,打印 2**100 ,结果会在末尾加字母 L 表⽰它是长整数。
但是到了 Python 3,情况就不同了:它仅有⼀种内置的整数,表⽰为 int,形式上是 Python 2 的短整数,但实际上它能表⽰的范围⽆限,⾏为上更像是长整数。⽆论多⼤的数,结尾都不需要字母 L 来作区分。
也就是说,Python 3 整合了两种整数表⽰法,⽤户不再需要⾃⾏区分,全交给底层按需处理。
理论上,Python 3 中的整数没有上限(只要不超出内存空间)。这就解释了前⽂中直接打印两数相乘,为什么结果会正确了。
PEP-237(Unifying Long Integers and Integers)中对这个转变作了说明。它解释这样做的 ⽬的:
这会给新的 Python 程序员(⽆论他们是否是编程新⼿)减少⼀项上⼿前要学的功课。
Python 在语⾔运⽤层屏蔽了很多琐碎的活,⽐如内存分配,所以,我们在使⽤字符串、列表或字典等对象时,根本不⽤操⼼。整数类型的转变,也是出于这样的便利⽬的。(坏处是牺牲了⼀些效率,在此就不谈了)
回到前⾯的第⼆个话题:Numpy 中整数的上限是多少?
由于它是 C 语⾔实现,在整数表⽰上,⽤的是 C 语⾔的规则,也就是会区分整数和长整数。
有⼀种⽅式可查看:
import numpy as np
a = np.arange(2)
type(a[0])
# 结果:numpy.int32
也就是说它默认的整数 int 是 32 位,表⽰范围在 -2147483648 ~ 2147483647。
对照前⽂的截图,⾥⾯只有两组数字相乘时没有溢出:100007*4549、100012*13264,其它数据组都溢出了,所以出现奇怪的负数结果。
Numpy ⽀持的数据类型要⽐ Python 的多,相互间的区分界限很多样:
要解决整数溢出问题,可以通过指定 dtype 的⽅式:
import numpy as np
q = [100000]
w = [500000]
# ⼀个溢出的例⼦:
a = np.array(q)
b = np.array(w)
print(a*b) # 产⽣溢出,结果是个奇怪的数值
# ⼀个解决的例⼦:
c = np.array(q, dtype='int64')
d = np.array(w, dtype='int64')
print(c*d) # 没有溢出:[50000000000]
好了,前⾯提出的问题就回答完了。来作个结尾吧:
Python 3 极⼤地简化了整数的表⽰,效果可表述为:整数就只有⼀种整数(int),没有其它类型的整数(long、int8、int64 之类的)
Numpy 中的整数类型对应于 C 语⾔的数据类型,每种“整数”有⾃⼰的区间,要解决数据溢出问题,需要指定更⼤的数据类型(dtype)
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持我们。
时间: 2019-09-09

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。