Python 的整数与 Numpy 的数据溢出

开发 后端
经过学习群里的一番讨论,我才终于明白是怎么回事,所以本文把相关知识点做个梳理。一起来看看吧。

 [[411683]]

某位 A 同学发了我一张截图,问为何结果中出现了负数?

看了图,我第一感觉就是数据溢出了。数据超出能表示的最大值,就会出现奇奇怪怪的结果。

然后,他继续发了张图,内容是 print(100000*208378),就是直接打印上图的 E[0]*G[0],结果是 20837800000,这是个正确的结果。

所以新的问题是:如果说上图的数据溢出了,为何直接相乘的数却没有溢出?

由于我一直忽视数据的表示规则(整型的上限是多少?),而且对 Numpy 了解不多,还错看了图中结果,误以为每一个数据都是错误的,所以就解答不出来。

最后,经过学习群里的一番讨论,我才终于明白是怎么回事,所以本文把相关知识点做个梳理。

在开始之前,先总结一下上图会引出的话题:

  •  Python 3 中整数的上限是多少?Python 2 呢?
  •  Numpy 中整数的上限是多少?整数溢出该怎么办?

对于第一个问题,两个版本的 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 语言的规则,也就是会区分整数和长整数。

有一种方式可查看: 

  1. import numpy as np  
  2. a = np.arange(2)  
  3. type(a[0])  
  4. # 结果:numpy.int32 

也就是说它默认的整数 int 是 32 位,表示范围在 -2147483648 ~ 2147483647。

对照前文的截图,里面只有两组数字相乘时没有溢出:100007*4549、100012*13264,其它数据组都溢出了,所以出现奇怪的负数结果。

Numpy 支持的数据类型要比 Python 的多,相互间的区分界限很多样:

截图来源:https://www.runoob.com/numpy/numpy-dtype.html

要解决整数溢出,可通过指定 dtype 的方式: 

  1. import numpy as np  
  2. q = [100000]  
  3. w = [500000]  
  4. # 一个溢出的例子:  
  5. a = np.array(q)  
  6. b = np.array(w)  
  7. print(a*b)  # 产生溢出,结果是个奇怪的数值  
  8. # 一个解决的例子:  
  9. c = np.array(q, dtypeint64 )  
  10. d = np.array(w, dtypeint64 )  
  11. print(c*d) # 没有溢出:[50000000000] 

好了,前面提出的问题就回答完了。

来作个结尾吧:

  •  Python 3 极大地简化了整数的表示,效果可表述为:整数就只有一种整数(int),没有其它类型的整数(long、int8、int64 之类的)
  •  Numpy 中的整数类型对应于 C 语言的数据类型,每种“整数”有自己的区间,要解决数据溢出问题,需要指定更大的数据类型(dtype) 

 

责任编辑:庞桂玉 来源: 机器学习算法与Python学习
相关推荐

2021-08-19 16:56:37

Python内存开发

2016-09-19 10:14:54

PythonNumpy数据

2015-03-30 11:18:50

内存管理Android

2009-09-04 10:37:50

Java堆栈溢出

2024-06-06 09:08:14

NumPyPython数据分析

2010-09-25 11:23:15

Java内存泄露

2023-11-23 08:58:45

PythonNumPy

2022-06-27 08:31:29

数据溢出无符号

2021-05-22 09:44:21

PythonNumpy数组Python矩阵

2020-11-05 11:30:46

PythonNumPy数组

2012-05-15 02:04:22

JVMJava

2020-07-09 10:29:29

数据中心IT技术

2024-03-11 08:22:40

Java内存泄漏

2020-11-13 09:31:44

分治算法运算

2019-10-25 15:44:10

Pythonnumpy数组分析

2021-12-17 08:27:55

NumpyPython 机器学习

2020-12-15 10:14:47

NumPynanPython

2024-09-09 09:41:03

内存溢出golang开发者

2019-09-11 14:34:13

排序算法数据科学

2022-02-18 12:24:39

PythonNumpy Arra大数据
点赞
收藏

51CTO技术栈公众号