微积分计算
多项式的微积分
多项式微分
matlab中使用向量来表示多项式.即在向量中只存储多项式对应次数项的系数即可. 比如多项式f ( x ) = x 3 − 2 x − 5 f(x)=x^{3}-2 x-5 f ( x ) = x 3 − 2 x − 5 在MATLAB中可以表示为 p=[1 0 -2 -5 ];
使用polyval
函数可以获得多项式函数在某些点处的值, 得到这些函数值后就可以通过plot
函数来绘制多项式函数的图像.比如想要绘制9 x 3 − 5 x 2 + 3 x + 7 9 x^{3}-5 x^{2}+3 x+7 9 x 3 − 5 x 2 + 3 x + 7 在− 2 ≤ x ≤ 5 -2 \leq x \leq 5 − 2 ≤ x ≤ 5 处的函数图像, 可以通过执行下面的代码实现.
1 2 3 4 5 a = [9 ,-5 ,3 ,7 ]; x = -2 :0.01 :5 ; f = polyval(a,x); plot (x,f,'LineWidth' , 2 );xlabel('x' ); ylabel('f(x)' ); set(gca,'FontSize' , 14 )
画出的图形如下:
多项式函数的求导可以使用polyder
函数来实现, 既然多项式表示成向量形式, 那其导函数自然也是向量形式.
对于求函数f ( x ) = 5 x 4 − 2 x 2 + 1 f(x)=5 x^{4}-2 x^{2}+1 f ( x ) = 5 x 4 − 2 x 2 + 1 在x=7处的导数的问题, 可以通过polyval
函数和polyder
函数共同实现.
1 2 3 p=[5 0 -2 0 1 ]; polyder(p) polyval(polyder(p),7 )
其结果为:
可以验证其结果是正确的的.
练习: 绘制多项式函数图像及其导数图像
f ( x ) = ( 5 x 3 − 7 x 2 + 5 x + 10 ) ( 4 x 2 + 12 x − 3 ) f(x)=\left(5 x^{3}-7 x^{2}+5 x+10\right)\left(4 x^{2}+12 x-3\right)
f ( x ) = ( 5 x 3 − 7 x 2 + 5 x + 1 0 ) ( 4 x 2 + 1 2 x − 3 )
其范围在− 2 ≤ x ≤ 1 -2 \leq x \leq 1 − 2 ≤ x ≤ 1
提示: 可能用到的函数conv()
参考代码
1 2 3 4 5 6 7 8 9 10 11 p=[5 -7 5 10 ]; q=[4 12 -3 ]; f=conv(p,q); df=polyder(f); x=linspace (-2 ,1 ); hold onplot (x,polyval(f,x),'r' ,'LineWidth' , 2 );plot (x,polyval(df,x),'--b' ,'LineWidth' , 2 );hold offset(gca,'FontSize' , 14 ); legend ('f(x)' ,'f^{\prime}(x)' );
参考效果图:
多项式积分
多项式函数的积分使用polyint
来实现, 需要注意的是, 对于一个多项式函数, 其不定积分结果有无穷多个, 因此在使用polyint
函数来求积分时, 不仅要给定一个被积函数, 还需要给出积分结果的常数项的值.
下述代码实现对多项式f ( x ) = 5 x 4 − 2 x 2 + 1 f(x)=5x^4-2x^2+1 f ( x ) = 5 x 4 − 2 x 2 + 1 的积分, 令常数项为3, 并计算积分后函数在x=7处的函数值.
1 2 3 p=[5 0 -2 0 1 ]; polyint(p, 3 ) polyval(polyint(p, 3 ),7 )
计算结果:
数值微积分
对于一般的曲线函数, 比如f ( x ) = s i n x f(x)=sinx f ( x ) = s i n x 等, matlab计算其导数的方法使用的导数定义法, 即通过导数定义式计算每个点的导数值.
f ′ ( x 0 ) = lim h → 0 f ( x 0 + h ) − f ( x 0 ) h f^{\prime}\left(x_{0}\right)=\lim _{h \rightarrow 0} \frac{f\left(x_{0}+h\right)-f\left(x_{0}\right)}{h}
f ′ ( x 0 ) = h → 0 lim h f ( x 0 + h ) − f ( x 0 )
数值微分
对于这样一个复杂的导数定义式, 我们可以分步对它进行计算. 先计算出Δ y \Delta y Δ y 和Δ x \Delta x Δ x , 在计算其比值.
matlab中提供diff
函数可以用来计算向量中相邻两个数的差值. 例如:
1 2 3 4 x = [1 2 5 2 1 ]; diff(x); ans = [1 3 -3 1 ]
不难发现, 使用diff
函数求得的结果值, 就是我们需要的一系列的Δ x \Delta x Δ x 的值. 因此, 想要求曲线的导数值, 只需用diff(y)
除以diff(x)
即可.
1 2 3 4 5 x0 = pi /2 ; h = 0.1 ; x = [x0 x0+h]; y = [sin (x0) sin (x0+h)]; m = diff(y)./diff(x)
结果为:
由于, sin(x)在x = π / 2 x=\pi/2 x = π / 2 处的导数值是0, 不是-0.05, 因此, 这种计算导数的方式是一种逼近式的计算, 我们可以通过调整h的大小, 来不断的提高精度.
练习:
计算f ( x ) = s i n ( x ) f(x)=sin(x) f ( x ) = s i n ( x ) 在x = π / 2 x=\pi/2 x = π / 2 处的导数值, 分别取h= 0.1,0.01,0.001,0.0001,0.00001,0.000001,0.0000001观察结果.
参考代码:
1 2 3 4 5 6 7 8 9 h=[0.1 0.01 0.001 0.0001 0.00001 0.000001 0.0000001 ]; x0=pi /2 ; m=zeros (size (h)); for ii=1 :size (h,2 ) x=[x0 x0+h(ii)]; y=[sin (x0) sin (x0+h(ii))]; m(ii)=diff(y)./diff(x); end m
执行结果:
可以看到, 误差逐渐变小, 由于精度提高, 后三位数显示的都是0; 可以通过执行format long
来得到更加精确的数值.
相同的思想可以计算出f ( x ) = s i n ( x ) f(x)=sin(x) f ( x ) = s i n ( x ) 在区间[ 0 , 2 π ] [0 ,2\pi] [ 0 , 2 π ] 上的导函数.
1 2 3 4 h = 0.5 ; x = 0 :h:2 *pi ; y = sin (x); m = diff(y)./diff(x);
进而可以绘制出导函数的图像.我们可以尝试使用不同的步长 h 来绘制导函数的图像.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 g = colormap(lines); hold on;for i =1 :4 x = 0 :power(10 , -i ):pi ; y = sin (x); m = diff(y)./diff(x); plot (x(1 :end -1 ), m, 'Color' , g(i ,:)); end hold off;set(gca,'XLim' , [0 , pi /2 ]); set(gca,'YLim' , [0 , 1.2 ]); set(gca,'FontSize' , 18 ); set(gca,'FontName' ,'symbol' ); set(gca,'XTick' , 0 :pi /4 :pi /2 ); set(gca,'XTickLabel' , {'0' , 'pi/4' , 'pi/2' }); h = legend ('h=0.1' ,'h=0.01' ,'h=0.001' ,'h=0.0001' ); set(h,'FontName' , 'Times New Roman' ); box on;
结果图形:
这看起来是两条线, 是因为随h的减小, 精度越来越高导致有一定的重合, 可以通过点击放大发现存在着不同的曲线.
练习: 绘制函数f ( x ) = e − x sin ( x 2 / 2 ) f(x)=e^{-x} \sin \left(x^{2} / 2\right) f ( x ) = e − x sin ( x 2 / 2 ) 的导数图像, 分别采用h=0.1,0.01,0.001.
参考代码
1 2 3 4 5 6 7 8 9 10 11 g = colormap(lines); hold on;for i =1 :3 x = 0 :power(10 , -i ):2 *pi ; y = exp (-x).*sin (x.*x/2 ); m = diff(y)./diff(x); plot (x(1 :end -1 ), m, 'Color' , g(i ,:)); end hold off;set(gca,'XTick' , 0 :pi /4 :2 *pi ); legend ('h=0.1' ,'h=0.01' ,'h=0.001' );
参考结果图:
根据高阶导数的定义, 高阶导数只不过是其低一阶导函数的导数. 利用这一思想, 可以计算函数的二阶导数, 三阶导数等等.
1 2 3 4 5 6 7 8 x = -2 :0.005 :2 ; y = x.^3 ; m = diff(y)./diff(x); m2 = diff(m)./diff(x(1 :end -1 )); plot (x,y,x(1 :end -1 ),m,x(1 :end -2 ),m2); xlabel('x' ,'FontSize' , 18 ); ylabel('y' ,'FontSize' , 18 ); legend ('f(x) =x^3' ,'f^{\prime}(x)' ,'f^{\prime \prime}(x)' );set(gca,'FontSize' , 18 );
数值积分
根据定积分的几何意义可知, 求一个函数的定积分, 就是求函数图像与坐标轴和积分边界所围成的图形的面积. matlab中使用的是定积分的定义去进行计算, 即"大化小, 常代变"的思想. 把需要计算分面积分割成若干小部分, 计算这些部分图形的面积和.
在图形分割的过程中, 可以使用不同的分割策略, 即使用不同的可计算的多边形面积代替曲边梯形的面积.这里介绍中点规则
, 梯形规则
和辛普森规则
中点规则
其原理是使用分割边界的中点处的函数值作为分割小矩形的高.即
∫ x 0 x 3 f ( x ) d x ≈ h f 0 + h f 1 + h f 2 = h ∑ i = 0 n − 1 f i \int_{x_{0}}^{x_{3}} f(x) d x \approx h f_{0}+h f_{1}+h f_{2}=h \sum_{i=0}^{n-1} f_{i}
∫ x 0 x 3 f ( x ) d x ≈ h f 0 + h f 1 + h f 2 = h i = 0 ∑ n − 1 f i
原理图如下:
根据此原理, 计算
A = ∫ 0 2 4 x 3 d x = x 4 ∣ 0 2 = ( 2 ) 4 − ( 0 ) 4 = 16 A=\int_{0}^{2} 4 x^{3} d x=\left.x^{4}\right|_{0} ^{2}=(2)^{4}-(0)^{4}=16
A = ∫ 0 2 4 x 3 d x = x 4 ∣ ∣ 0 2 = ( 2 ) 4 − ( 0 ) 4 = 1 6
1 2 3 4 5 h = 0.05 ; x = 0 :h:2 ; midpoint = (x(1 :end -1 )+x(2 :end ))./2 ; y = 4 *midpoint.^3 ; s = sum(h*y)
上述代码的计算结果为:
结果与正确结果16之间存在一定误差, 可以通过减小步长h的方式 来更加细分, 以提高计算精度.
梯形规则
梯形规则的原理是 不再使用小矩形代替曲边梯形, 而是使用直边梯形代替曲边梯形. 即,
∫ x 0 x 3 f ( x ) d x ≈ h f 0 + f 1 2 + h f 1 + f 2 2 + h f 2 + f 3 2 \int_{x_{0}}^{x_{3}} f(x) d x \approx h \frac{f_{0}+f_{1}}{2}+h \frac{f_{1}+f_{2}}{2}+h \frac{f_{2}+f_{3}}{2}
∫ x 0 x 3 f ( x ) d x ≈ h 2 f 0 + f 1 + h 2 f 1 + f 2 + h 2 f 2 + f 3
原理示意图:
使用此方法再次计算
A = ∫ 0 2 4 x 3 d x = x 4 ∣ 0 2 = ( 2 ) 4 − ( 0 ) 4 = 16 A=\int_{0}^{2} 4 x^{3} d x=\left.x^{4}\right|_{0} ^{2}=(2)^{4}-(0)^{4}=16
A = ∫ 0 2 4 x 3 d x = x 4 ∣ ∣ 0 2 = ( 2 ) 4 − ( 0 ) 4 = 1 6
1 2 3 h = 0.05 ; x = 0 :h:2 ; y = 4 *x.^3 ; trapezoid = (y(1 :end -1 )+y(2 :end ))/2 ; s = h*sum(trapezoid)
可以直接使用trapz
函数来计算trapezoid = (y(1:end-1)+y(2:end))/2;
上述代码等价为
1 2 h = 0.05 ; x = 0 :h:2 ; y = 4 *x.^3 ; s = h*trapz(y)
执行结果均为:
辛普森规则
辛普森规则的原理推导比较复杂, 这里给出其原理的结论:
∫ x 0 x 2 f ( x ) d x ≈ h 3 ( f 0 + 4 f 1 + f 2 ) \int_{x_{0}}^{x_{2}} f(x) d x \approx \frac{h}{3}\left(f_{0}+4 f_{1}+f_{2}\right)
∫ x 0 x 2 f ( x ) d x ≈ 3 h ( f 0 + 4 f 1 + f 2 )
这个方法一次计算两个步长, 也就是说第一次计算x 0 x_0 x 0 到x 2 x_2 x 2 , 下一个参与计算的单元为 x 2 x_2 x 2 到x 4 x_4 x 4 ,原理图如下:
使用此规则计算这个积分
A = ∫ 0 2 4 x 3 d x = x 4 ∣ 0 2 = ( 2 ) 4 − ( 0 ) 4 = 16 A=\int_{0}^{2} 4 x^{3} d x=\left.x^{4}\right|_{0} ^{2}=(2)^{4}-(0)^{4}=16
A = ∫ 0 2 4 x 3 d x = x 4 ∣ ∣ 0 2 = ( 2 ) 4 − ( 0 ) 4 = 1 6
1 2 3 h = 0.05 ; x = 0 :h:2 ; y = 4 *x.^3 ; s = h/3 *(y(1 )+2 *sum(y(3 :2 :end -2 ))+... 4 *sum(y(2 :2 :end ))+y(end ))
计算结果为:
这种方法是这三种方法中计算精度最高的方法.
下图中比较了这三种计算方式的区别:
可以理解为, 矩形规则是在用0次曲线逼近, 梯形规则是在用1次曲线逼近, 而辛普森规则使用二次曲线逼近.
内置积分函数
首先复习一下matlab的函数句柄, 以及使用方式.
函数句柄类似于C++中的指针, 它是指向了一个函数. 以下面代码为例介绍函数句柄.
1 2 3 4 5 6 function [y] = xy_plot (input,x) y = input(x); plot (x,y,'r--' ); xlabel('x' ); ylabel('function(x)' ); end
使用此函数绘图应该传入一个函数句柄, 而不是函数的名称, 正确的使用方式为:
1 2 3 xy_plot(@sin ,0 :0.01 :2 *pi ); xy_plot(@cos ,0 :0.01 :2 *pi ); xy_plot(@exp ,0 :0.01 :2 *pi );
matlab中计算积分的函数是integral
函数, 参数为被积函数和上下限. 此处传入函数应该传入其函数句柄.
结果是:
也可以传入我们自定义函数.下面给出计算这个积分的代码.
A = ∫ 0 2 4 x 3 d x = x 4 ∣ 0 2 = ( 2 ) 4 − ( 0 ) 4 = 16 A=\int_{0}^{2} 4 x^{3} d x=\left.x^{4}\right|_{0} ^{2}=(2)^{4}-(0)^{4}=16
A = ∫ 0 2 4 x 3 d x = x 4 ∣ ∣ 0 2 = ( 2 ) 4 − ( 0 ) 4 = 1 6
1 2 f=@(x) 4 *x.^3 ; integral(f,0 ,2 )
结果为:
计算二重积分和三重积分使用函数integral2
和integral3
, 下面给出使用示例.
计算: f ( x , y ) = ∫ 0 π ∫ π 2 π ( y ⋅ sin ( x ) + x ⋅ cos ( y ) ) d x d y f(x, y)=\int_{0}^{\pi} \int_{\pi}^{2 \pi}(y \cdot \sin (x)+x \cdot \cos (y)) d x d y f ( x , y ) = ∫ 0 π ∫ π 2 π ( y ⋅ sin ( x ) + x ⋅ cos ( y ) ) d x d y
1 2 f = @(x,y) y.*sin (x)+x.*cos (y); integral2(f,pi ,2 *pi ,0 ,pi )
计算: f ( x , y ) = ∫ − 1 1 ∫ 0 1 ∫ 0 π ( y ⋅ sin ( x ) + z ⋅ cos ( y ) ) d x d y d z f(x, y)=\int_{-1}^{1} \int_{0}^{1} \int_{0}^{\pi}(y \cdot \sin (x)+z \cdot \cos (y)) d x d y d z f ( x , y ) = ∫ − 1 1 ∫ 0 1 ∫ 0 π ( y ⋅ sin ( x ) + z ⋅ cos ( y ) ) d x d y d z
1 2 f = @(x,y,z) y.*sin (x)+z.*cos (y); integral3(f,0 ,pi ,0 ,1 ,-1 ,1 )
资料链接
参考视频
参考讲义