问题描述:已知函数f(x),取定义域内一组离散点,利用该组离散点及其函数值拟合求出区间内定积分,并与在原函数上直接积分的结果作比较。
根据微分的思想,我们可以根据这些离散点及其函数值求n个小梯形的面积之和,但这无疑是件复杂的工程,于是我的想法是利用这些离散点拟合一个函数表达式,然后求积分。
工具:python scipy库,numpy库,matplotlib库
import numpy as npimport matplotlib.pyplot as pltfrom scipy import integratefrom scipy.optimize import curve_fit
若还未安装这些库,在命令行安装即可,以scipy为例,其余类似
pip install scipy
自定义一个函数表达式(原函数),可以复杂也可以简单
f(x)=3x^3+5x^2+e^x+c
其中c为一个0-19范围内的随机数,目的在于使这些离散点不严格的按照函数表达式生成,使拟合结果更直观,否则,利用最小二乘法拟合而成的函数表达式将与原函数相差无几。
2. 选取离散点及其函数值
#构建自变量离散点x=np.array([0,0.5,1,1.5,2,2.5,3,3.5,4])#根据离散点求出函数f(x)的函数值y=[]for i in x:y.append(3*i*i*i+5*i*i+np.exp(i)+np.random.randint(20))y=np.array(y)
自定义函数模型,其中a,b,c,d均为系数
#自定义函数形式def f1(x,a,b,c,d):return a*np.power(x,3)+b*np.power(x,2)+c*np.exp(x)+d
利用最小二乘法拟合,并得到自定义函数里面的系数a b c d
#非线性最小二乘法拟合popt, pcov = curve_fit(f1, x, y)#popt里面是拟合系数a = popt[0] b = popt[1]c = popt[2]d = popt[3]yvals = f1(x,a,b,c,d) #拟合y值
绘图直观了解拟合效果
#绘图plot1 = plt.plot(x, y,color='blue',label='原函数')plot2 = plt.plot(x, yvals,color='red',label='拟合函数')plt.xlabel('x')plt.ylabel('y')plt.rcParams['font.sans-serif']=['SimHei']#设置中文plt.legend(loc=4) #指定legend的位置右下角plt.show()
计算积分
v1, err = integrate.quad(f1, 0, 4,args=(a,b,c,d))print('原函数从0-4积分结果为:',v1)v = integrate.trapz(yvals, x)print('拟合函数从0-4积分为结果为:',v)
拟合效果:
以及积分计算结果:
从积分结果可以看出,利用这种方法进行拟合得到的结果还是比较可靠的。