基于np.arange与np.linspace细微区别(数据溢出问题)

目录
  • 太长不看的简洁版本
    • 问题前夕
    • 我的代码
    • 同门的代码
    • 代码对比【区别只体现在自变量x】
    • 官方API解析
    • 解决办法

太长不看的简洁版本

1.x = np.arange(start, end, steps)

Values are generated within the half-open interval [start, stop)
(in other words, the interval including start but excluding stop).

  • 即区间是左闭右开的,不包含end的取值

2.x = np.linspace(start, end, num, endpoint=True)

There are num equally spaced samples in the closed interval [start, stop] or the half-open interval [start, stop) (depending on whether endpoint is True or False).

  • 即endpoint=True区间是左闭右闭的,包含end的取值
  • 即endpoint=False区间是左闭右开的,不包含end的取值

最终结论:

  • 当linspace函数指定参数endpoint=False时,两个函数的效果等价。
  • 当steps和num指定参数都是整数时,arrange会返回numpy.int32数据类型,
  • 而linspace会返回numpy.float数据类型,对应于 C 语言数据类型,每种“整数”有自己的区间,会遇到数据溢出的问题,数值分析中函数绘制曲线将得不到正确的答案。

解决方案:

  • 使用 np.linspace比np.arange好,可以预防数据溢出的问题
  • 使用np.arange时,将步长steps设置为小数,比如1.0

绘制曲线代码:

x = np.arange(0,100,1.0)                           #自变量的范围
x = np.linspace(0, 100, 100,endpoint=False)       # 两者效果等价
y = alpha*(T-x) + beta*(T**4-x**4) + gamma*(u**2)  #因变量
plt.plot(x, y, y*0.0)                              #曲线绘制

问题前夕

数值分析课程作业用python的matplotlib一直得不到正确的曲线图,后用Matlab就可以,明明是一样的函数,但是两者绘制出来的曲线图显示零点不一致,差距很大。

作为一枚不会matlab的学渣,为了得到正确的答案,难道真的必须啃下matlab的语法吗…又问了一下同门,他居然用python得出了正确的答案,排查两个小时一无所获转战Matlab的我留下了羡慕的泪水,赶紧要来了他的代码进行对比实验,终于找出了问题的关键了,预知后事如何请继续往下看…

我的代码

u = 21.0
T = 293.15
alpha = 50.0
beta = 2*(10**(-7))
gamma = 800.0
x = np.arange(0,10000,1)                           #自变量的范围
y = alpha*(T-x) + beta*(T**4-x**4) + gamma*(u**2)  #因变量
plt.plot(x, y, y*0.0)

效果图

从图中可以看出函数的零点在[7000,8000]这个范围。

那么问题来了,为什么表达式不是一次函数绘制出来的图形却是一条直线,x^4怎么也不能是一条直线吧???带着这个疑惑,我找了同学要了他的答案来对照,发现零点只有一个,在[1000,1200]这个范围内。我仔细对照了函数方程,苦苦思索了两个小时也没找到答案。

同门的代码

u = 21.0
T = 293.15
alpha = 50.0
beta = 2*(10**(-7))
gamma = 800.0
start = 1000
end = 1500
step = 1
num = (end - start) // step
x = np.linspace(start, end, num)
y = alpha*(T-x) + beta*(T**4-x**4) + gamma*(u**2)
fig = plt.figure(figsize=(6, 6))
plt.plot(x, y, label='Numerical Analysis')
plt.grid(True)
plt.xlim((800, 1500))  # 显示的x的范围(不设置则由程序自动设置)
plt.ylim((-10, 10))  # 显示的y的范围
plt.legend()           # 显示旁注
plt.show(fig)          # 没有输入值默认展示所有对象

效果图

从图中可以看出同门的代码跑出来的结果是正确的,并且这条线还是弯的…我以为是plt叠加导致的buff加成,然后我把作图的代码copy到我的代码里,仍然是错误的!!!在逐步分析后,我发现导致这个现象的原因居然只是一行代码的差距!!!展示如下:

代码对比【区别只体现在自变量x】

u = 21.0
T = 293.15
alpha = 50.0
beta = 2*(10**(-7))
gamma = 800.0
x = np.arange(1000,1500,1)           #区别只体现在自变量x所用的函数
#x = np.linspace(1000, 1500, 500)    #区别只体现在自变量x所用的函数
y = alpha*(T-x) + beta*(T**4-x**4) + gamma*(u**2)
plt.plot(x, y)

x = np.arange(1000,1500,1)的效果图

[<matplotlib.lines.Line2D at 0x29e40ceff10>]

x = np.linspace(1000, 1500, 500)的效果图

[<matplotlib.lines.Line2D at 0x29e40da97c0>]

x = np.arange(1000,1500,0.1)的效果图

咦,此时我不禁疑惑,我使用的np.arange也是1000-1500,以1为间隔,自变量取值为

[1000, 1001, 1002,…, 1499]

使用的np.linspace也是把1000-1500切分为500份,

[1000, 1001.00200401, 1002.00400802, …, 1498.99799599, 1500]

效果理应是差不多的。

但是为什么我用arange函数的时候需要将精度设为0.1,才能实现linspace精度为1的效果呢???

官方API解析

x = np.arange(0,10,1)
#输出: [0 1 2 3 4 5 6 7 8 9]
x1 = np.linspace(0, 10, 10, endpoint=False)
#输出:[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
x1 = np.linspace(0, 10, 10)
#输出:[ 0.          1.11111111  2.22222222  3.33333333  4.44444444  5.55555556
  6.66666667  7.77777778  8.88888889 10.        ]

上面的例子表明:当指定endpoint为False时,两个函数的效果等价。此时,我似乎发现了一点不对劲,一个输出的是整数,一个输出的是小数???会不会这个对结果造成了影响呢?怀着想都不敢想的梦想,我尝试了一下将整数设置为浮点数…

x = np.arange(1000,1500,1.0)的效果图

我的天呀,居然把取样间隔从1设置为1.0效果居然有这么大的不同,此时我的疑惑非但没有减轻,反而更加疑惑了,整数和浮点数作图效果的天差地别,又是什么原因导致的呢?我想了想,毕竟我学的这门课叫做《数值分析》啊,那我毕竟也得有点这方面的一点见解?…也许这个表达式太过于复杂,整数输进去再经过七七七八八的加减乘除后,自变量为整型+1、-1差别很细微可以忽略不计。最主要是我的因变量的范围是10^5,微小的变化也许体现不出来???但是我的常量设置的时候特地全都设置为浮点数了。

通过MATLAB已知零点在[1118,1119]之间,我特地打印出x=1118和x=1119对应因变量的值:

x1 = 1118;      #对应因变量y=572.5297745541902
x2 = 1119;      #对应因变量y=-596.9030544458074
x = np.arange(1110,1120,1.0)  

输出:

[9820.44892975 8674.86472155 7526.31814255 6374.80385755 5220.31652655
 4062.85080475 2902.40134255 1738.96278555  572.52977455 -596.90305445]
x = np.arange(1110,1120,1)

输出:

[313045.14002735 313617.54273755 313327.98961775 313035.46879195
 313598.96837935 313300.49611675 312999.04011375 312694.59501595
 313246.14892335 312935.70955355]

由x1,x2可以看出零点确实在这个范围内,但是自变量为整型时,很有可能是溢出了,导致计算值与真实值天差地别。不但正数数值不对,而且零点也消失了。但是我单独输入1119也是整型,为什么可以得到正确值?python最新版本对整型没有限制了,原来能表示的最大整型为9223372036854775807。Numpy 中的整数类型对应于 C 语言的数据类型,每种“整数”有自己的区间,要解决数据溢出问题,需要指定更大的数据类型(dtype)!!!

原来我单独输入x的值,此时用的是python的版本表示的整型,是源码里自带了溢出防止办法,所以函数值能正确输出,但是x = np.arange(1110,1120,1),对应的每一个自变量的类型输出为:

<class ‘numpy.int32’>

只能表示数据范围整数(-2147483648 to 2147483647),当x取值为10^3时,对应四次方结果为1000000000000,已经超出可以表示的范围了。到这里已经把我的坑解释的很清楚了。

解决办法

大家以后要作图绘制曲线最好使用np.linspace,会自动把自变量取值设置为浮点型,或者np.arange(start,end,1.0),步长设置为浮点型!!!这样的话才不会出现溢出等问题!!!!

花了半天的时间终于把这个坑给解决了,给自己

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Python中range()与np.arange()的具体使用

    目录 np.arange() range() range()和np.arange()区别 np.arange() np.arange()函数返回一个有终点和起点的固定步长的排列,如[1,2,3,4,5],起点是1,终点是6,步长为1. 参数个数情况: np.arange()函数分为一个参数,两个参数,三个参数三种情况 一个参数时,参数值为终点,起点取默认值0,步长取默认值1. 两个参数时,第一个参数为起点,第二个参数为终点,步长取默认值1. 三个参数时,第一个参数为起点,第二个参数为终点,第三个

  • Python中range、np.arange和np.linspace的区别

    目录 1. range 2. numpy.arange 3. numpy.linspace 参考 1. range range是python内置的一个类,该类型表示一个不可改变(immutable)的数字序列,常常用于在for循环中迭代一组特殊的数,它的原型可以近似表示如下: class range(stop) class range(start, stop, step=1) (注意,Python是不允许定义两个类初始化函数的,其实其CPython实现更像是传入不定长参数*args,然后根据le

  • python np.arange 步长0.1的问题需要特别注意

    目录 np.arange 步长0.1问题 1)count输出什么? 2)count输出是什么? python步长的使用 np.arange 步长0.1问题 两个小测试: 1)count输出什么? import numpy as np y_min= 20 y_max= 21 step = 0.1 count = 0 for i in np.arange(y_min, y_max, step): count += 1 print('i:', count, i) 答案是:count = 10 如图 2

  • 基于np.arange与np.linspace细微区别(数据溢出问题)

    目录 太长不看的简洁版本 问题前夕 我的代码 同门的代码 代码对比[区别只体现在自变量x] 官方API解析 解决办法 太长不看的简洁版本 1.x = np.arange(start, end, steps) Values are generated within the half-open interval [start, stop)(in other words, the interval including start but excluding stop). 即区间是左闭右开的,不包含en

  • python中np.multiply()、np.dot()和星号(*)三种乘法运算的区别详解

    为了区分三种乘法运算的规则,具体分析如下: import numpy as np 1. np.multiply()函数 函数作用 数组和矩阵对应位置相乘,输出与相乘数组/矩阵的大小一致 1.1数组场景 A = np.arange(1,5).reshape(2,2) A array([[1, 2],        [3, 4]]) B = np.arange(0,4).reshape(2,2) B array([[0, 1],        [2, 3]]) np.multiply(A,B) #数

  • numpy中np.nanmax和np.max的区别及坑

    目录 np.nanmax和np.array([1,2,3,np.nan]).max()的区别 原理 速度区别 numpy中nan和常用方法 np.nanmax和np.array([1,2,3,np.nan]).max()的区别 numpy中numpy.nanmax的官方文档 原理 在计算dataframe最大值时,最先用到的一定是Series对象的max()方法(),最终结果是4. s1 = pd.Series([1,2,3,4,np.nan]) s1_max = s1.max() 但是笔者由于

  • 对python中arange()和linspace()的区别说明

    arange()类似于内置函数range(),通过指定开始值.终值和步长创建表示等差数列的一维数组,注意得到的结果数组不包含终值. linspace()通过指定开始值.终值和元素个数创建表示等差数列的一维数组,可以通过endpoint参数指定是否包含终值,默认值为True,即包含终值. 补充知识:python实现n阶乘0尾数计算案例 我就废话不多说了,大家还是直接看代码吧! class Solution: """ @param: n: An integer @return:

  • 浅谈numpy中np.array()与np.asarray的区别以及.tolist

    array和asarray都可以将结构数据转化为ndarray,但是主要区别就是当数据源是ndarray时,array仍然会copy出一个副本,占用新的内存,但asarray不会. 1.输入为列表时 a=[[1,2,3],[4,5,6],[7,8,9]] b=np.array(a) c=np.asarray(a) a[2]=1 print(a) print(b) print(c) 从中我们可以看出np.array与np.asarray功能是一样的,都是将输入转为矩阵格式.当输入是列表的时候,更改

  • 基于numpy.random.randn()与rand()的区别详解

    numpy 中有一些常用的用来产生随机数的函数,randn()和rand()就属于这其中. numpy.random.randn(d0, d1, -, dn) 是从标准正态分布中返回一个或多个样本值. numpy.random.rand(d0, d1, -, dn) 的随机样本位于[0, 1)中. import numpy as np arr1 = np.random.randn(2,4) print(arr1) print('**********************************

  • python多项式拟合之np.polyfit 和 np.polyld详解

    python数据拟合主要可采用numpy库,库的安装可直接用pip install numpy等. 1. 原始数据:假如要拟合的数据yyy来自sin函数,np.sin import numpy as np import matplotlib.pyplot as plt xxx = np.arange(0, 1000) # x值,此时表示弧度 yyy = np.sin(xxx*np.pi/180) #函数值,转化成度 2. 测试不同阶的多项式,例如7阶多项式拟合,使用np.polyfit拟合,np

随机推荐