先看下面这道题:
1. 题目
想要用少数几个点计算估算出面积,我们应该要考虑以下两个方面:
- 用点拟合出一条曲线
- 使用曲线进行积分,从而计算出面积
那我们分别用matlab进行实现:
2. 曲线拟合
有了点的数据,自然可以使用matlab的polyfit函数进行拟合(官方文档)。
当然,直接拿原始数据进行拟合显然是不正确的:
1)不正确的做法
% 直接进行拟合
p=polyfit(x,y,2)
得到的结果就是:
p =
-0.0338 0.2766 4.1545
解释一下:这个p
即为次数为 n
的多项式 p(x)
的系数。
对于本题来说,对于二次多项式 p ( x ) = a x 2 + b x + c p(x)=ax^2+bx+c p(x)=ax2+bx+c, p = [ a , b , c ] p=[a,b,c] p=[a,b,c]
我们可以将其画出来进行对比:
x1=linspace(0,10);
y1 = polyval(p,x1);
plot(x1,y1); % 预测的折线图
hold on;
scatter(x,y); % 真实数据的散点图
结果为:
之所以产生这样的效果,当然是因为这16个点绝对不能被一个函数所拟合。想想高中学的函数的定义就知道了……
2)正确的做法(简单版)
考虑到了不能用一个函数所拟合,那么我们自然可以用多个函数进行分别拟合。
最简单的做法就是将上、下两条曲线分别拟合,完整代码如下:
clc;clear;
%%
load init.mat % 存储x和y
[max1,maxIndex]=max(x);
[min1,minIndex]=min(x);
%%
if(minIndex<maxIndex)
x1=x(minIndex:maxIndex);
y1=y(minIndex:maxIndex);
x2=[x(maxIndex:-1), x(1:minIndex)];
y2=[y(maxIndex:-1), y(1:minIndex)];
else
x1=x(maxIndex:minIndex);
y1=y(maxIndex:minIndex);
x2=[x(minIndex:-1), x(1:maxIndex)];
y2=[y(minIndex:-1), y(1:maxIndex)];
end
%%
p1=polyfit(x1,y1,2);
p2=polyfit(x2,y2,2);
%%
xx=linspace(0,10);
yy1 = polyval(p1,xx);
yy2 = polyval(p2,xx);
plot(xx,yy1); % 预测的折线图
hold on;
plot(xx,yy2);
scatter(x,y); % 真实数据的散点图
结果如下:
虽然看着感觉还是不靠谱,但是至少可以计算出一个解出来了
3)稍加改进(?)
假装没有看到题目的二阶光滑曲线(doge)
将原先的:p1=polyfit(x1,y1,2);p2=polyfit(x2,y2,2);
换成:
p1=polyfit(x1,y1,4);
p2=polyfit(x2,y2,4);
其实就是用更高维度的曲线进行拟合,这么拟合的结果稍微好一些:
3. 计算面积
只需要将上下两个函数分别求积分,即可得到结果:
clc;clear;
load init.mat;
load test2.mat;
minIndex=8;
maxIndex=16;
%% 求积分
syms a;
f1=poly2sym(p1);
f2=poly2sym(p2);
area1 = int(f1,x(minIndex),x(maxIndex));
area2 = int(f2,x(minIndex),x(maxIndex));
area = double(area1-area2)
使用二阶曲线进行拟合的结果为:
area =
47.7477
使用四阶曲线进行拟合的结果:
area =
50.8495