1.实验目的:
进一步熟悉曲线拟合的最小二乘法。
掌握编程语言字符处理程序的设计和调试技术。
2.实验要求:
输入:已知点的数目以及各点坐标 。
输出:根据最小二乘法原理以及各点坐标求出拟合曲线 。
3.程序流程:
(1)输入已知点的个数;
(2)分别输入已知点的X坐标;
(3)分别输入已知点的Y坐标;
(4)通过调用函数,求出拟合曲线。
最小二乘法原理如下:
根据一组给定的实验数据,求出自变量x与因变量y的函
4.难点,要根据已知坐标点求出多项式的系数。
5.程序流程图
6.源码(本程序已通过测试)
#include
#include
#define X 50
#define Y 50
float x[X],y[Y];
int n;//输入的数据总组数即坐标的总个数
void init();//初始化并输入相关数据
void confrim();//确认输入的数据
void deal();//根据输入的坐标点计算出拟合曲线
void modify();//用于修改输错的相应坐标这样可以避免一些数据重新输入
void main()
{
int select;
system("color f1");//dos命令使界面变颜色
init();//
confrim();
printf("请选择要拟合成几次多项式(提示:如果是一次函数就输入1二次函数就输入2):");
scanf("%d",&select);//输入你要选择拟合的函数的次数
deal(select);
}
void init()//初始化并输入相关数据
{
int i;
printf ("\n*********************************************************\n");
printf ("\n欢迎使用最小二乘法数据处理程序\n");
printf ("\n请输入您要处理的数据的组数(提示:程序定义一对x,y值为一组数据):");
while(1)
{
scanf("%d",&n);
if(n<=1)
{
printf("\n理的数据的组数不能小于或等于1");
printf ("\n请重新输入您要处理的数据的组数:");
}
else if(n>50)
{
printf ("\n对不起,本程序暂时无法处理50组以上的数据");
printf ("\n请重新输入您要处理的数据的组数:");
}
else break;
}
for (i=0;i
{
printf ("\n请输入第%d个x的值x%d=",i+1,i+1);
scanf ("%f",&x[i]);
printf ("\n请输入对应的y的值:y%d=",i+1);
scanf ("%f",&y[i]);
}
system("color f2");//
system("cls");//清屏
}
void deal(int select)//采用克莱默法则求解方程
{
int i;
float a0,a1,a2,temp,temp0,temp1,temp2;
float sy=0,sx=0,sxx=0,syy=0,sxy=0,sxxy=0,sxxx=0,sxxxx=0;//定义相关变量
for(i=0;i
{
sx+=x[i];//计算xi的和
sy+=y[i];//计算yi的和
sxx+=x[i]*x[i];//计算xi的平方的和
sxxx+=pow(x[i],3);//计算xi的立方的和
sxxxx+=pow(x[i],4);//计算xi的4次方的和
sxy+=x[i]*y[i];//计算xi乘yi的的和
sxxy+=x[i]*x[i]*y[i];//计算xi平方乘yi的和
}
temp=n*sxx-sx*sx;//方程的系数行列式
temp0=sy*sxx-sx*sxy;
temp1=n*sxy-sy*sx;
a0=temp0/temp;
a1=temp1/temp;
if(select==1)
{
printf("经最小二乘法拟合得到的一元线性方程为:\n");
printf("f(x)=%3.3fx+%3.3f\n",a1,a0);
system("pause");
}
temp=n*(sxx*sxxxx-sxxx*sxxx)-sx*(sx*sxxxx-sxx*sxxx)//方程的系数行列式
+sxx*(sx*sxxx-sxx*sxx);
temp0=sy*(sxx*sxxxx-sxxx*sxxx)-sxy*(sx*sxxxx-sxx*sxxx)
+sxxy*(sx*sxxx-sxx*sxx);
temp1=n*(sxy*sxxxx-sxxy*sxxx)-sx*(sy*sxxxx-sxx*sxxy)
+sxx*(sy*sxxx-sxy*sxx);
temp2=n*(sxx*sxxy-sxy*sxxx)-sx*(sx*sxxy-sy*sxxx)
+sxx*(sx*sxy-sy*sxx);
a0=temp0/temp;
a1=temp1/temp;
a2=temp2/temp;
if(select==2)
{
printf("经最小二乘法拟合得到的二次近似方程为:\n");
printf("f(x)=%3.3fx2+%3.3fx+%3.3f\n",a2,a1,a0);
system("pause");
}
}
void modify()//修改输错的相应坐标
{
int z;
char flag;
while(1)
{
printf("请输入你要修改的是第几组数据:");
scanf("%d",&z);
printf ("\n请输入你要修改的第%d个x的值x%d=",z,z);
scanf ("%f",&x[z-1]);
printf ("\n请输入你要修改的对应的y的值:y%d=",z);
scanf ("%f",&y[z-1]);
printf("是否继续修改数据是Y否N:");
getchar();
scanf("%c",&flag);
if(flag=='N'||flag=='n')
break;
}
system("cls");//清屏
confrim();
}
void confrim()
{
char flag;
int i;
while(1)
{
for(i=0;i
{
printf ("请输入第%d个x的值x%d=",i+1,i+1);
printf ("%f",x[i]);
printf (" 输入对应的y的值:y%d=",i+1);
printf("%f",y[i]);
printf("\n");
}
printf("确认你输入的数据是Y否N(即重新输入)修改M:");
getchar();
scanf("%c",&flag);
if(flag=='y'||flag=='Y')
break;
else if(flag=='n'||flag=='N')
init();
else
{
modify();
break;
}
}
}
测试
1拟合二次曲线结果(书上的)
2.拟合一次曲线结果