最小二乘法C语言的实现

1.实验目的:

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

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

2.实验要求:

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

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

3.程序流程:

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

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

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

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

最小二乘法原理如下:

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

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

5.程序流程图

6.源码(本程序已通过测试)

#include<stdio.h>
#include<math.h>
#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<n;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<n;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<n;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.拟合一次曲线结果

  • 25
    点赞
  • 160
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
加权最小二乘法是一种回归分析方法,它可以用来拟合带有权重的数据。在实现加权最小二乘法的时候,我们需要先定义一个数据结构来保存数据和权重。下面是一个简单的例子: ```c typedef struct { double x; double y; double weight; } Point; ``` 其中,`x` 和 `y` 表示数据的坐标,`weight` 表示权重。 接下来,我们需要实现一个函数来计算加权最小二乘法的系数。这个函数的输入是一个数组,包含了所有的数据点和权重,以及数据点的数量。输出是一个包含了两个系数的数组。 ```c void weighted_least_squares(Point *data, int n, double *coefficients) { double sum_x = 0.0; double sum_y = 0.0; double sum_xx = 0.0; double sum_xy = 0.0; double sum_w = 0.0; for (int i = 0; i < n; i++) { Point point = data[i]; double x = point.x; double y = point.y; double w = point.weight; sum_x += w * x; sum_y += w * y; sum_xx += w * x * x; sum_xy += w * x * y; sum_w += w; } double delta = sum_w * sum_xx - sum_x * sum_x; coefficients[0] = (sum_w * sum_xy - sum_x * sum_y) / delta; coefficients[1] = (sum_xx * sum_y - sum_xy * sum_x) / delta; } ``` 在这个函数中,我们利用加权最小二乘法的公式来计算系数。具体来说,我们需要计算下面这个方程组的解: ``` sum(w * x^2) * a + sum(w * x) * b = sum(w * x * y) sum(w * x) * a + sum(w) * b = sum(w * y) ``` 其中,`x` 和 `y` 分别是数据点的横坐标和纵坐标,`w` 是权重。这个方程组的解就是加权最小二乘法的系数。 最后,我们可以使用这个函数来计算任意数据集的加权最小二乘法系数。例如,下面是一个简单的例子: ```c int main() { Point data[] = {{1.0, 2.0, 1.0}, {2.0, 4.0, 2.0}, {3.0, 6.0, 3.0}}; double coefficients[2]; weighted_least_squares(data, 3, coefficients); printf("a = %f, b = %f\n", coefficients[0], coefficients[1]); return 0; } ``` 在这个例子中,我们定义了一个包含了三个数据点和权重的数组。然后,我们调用 `weighted_least_squares` 函数来计算加权最小二乘法系数,并输出结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值