一般最小二乘法 c语言,最小二乘法C语言的实现

1.实验目的:

进一步熟悉曲线拟合的最小二乘法。

掌握编程语言字符处理程序的设计和调试技术。

2.实验要求:

输入:已知点的数目以及各点坐标 。

输出:根据最小二乘法原理以及各点坐标求出拟合曲线 。

3.程序流程:

(1)输入已知点的个数;

(2)分别输入已知点的X坐标;

(3)分别输入已知点的Y坐标;

(4)通过调用函数,求出拟合曲线。

最小二乘法原理如下:

根据一组给定的实验数据,求出自变量x与因变量y的函

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

4.难点,要根据已知坐标点求出多项式的系数。

5.程序流程图

0818b9ca8b590ca3270a3433284dd417.png

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拟合二次曲线结果(书上的)

0818b9ca8b590ca3270a3433284dd417.png

2.拟合一次曲线结果

0818b9ca8b590ca3270a3433284dd417.png

你可能感兴趣的:(一般最小二乘法,c语言)