最小二乘法 C 语言
1.实验目的:
进一步熟悉曲线拟合的最小二乘法。
掌握编程语言字符处理程序的设计和调试技术。
2.实验要求:
输入:已知点的数目以及各点坐标 。
输出:根据最小二乘法原理以及各点坐标求出拟合曲线 。
3.程序流程:
输入已知点的个数;
分别输入已知点的 X 坐标;
分别输入已知点的 Y 坐标;
通过调用函数,求出拟合曲线。
最小二乘法原理如下:
根据一组给定的实验数据 ,求出自变量 x 与因变量 y 的函数
关系,只要求在给定点 上的误差 当
时,即
的平方和
(4.4.1)
最小.
这里
是线性无关的函数族,假定在
上给出一
组数据 ,
以及对应的一组权 ,这里
为权
系数,要求
(4.4.2)中
使
实际上是关于
最小,其中
(4.4.2)
的多元函数,求 I 的最小值就是
求多元函数 I 的极值,由极值必要条件,可得
(4.4.3) 根据内积定义引入相应带权内积记号
(4.4.4)
则(4.4.3)可改写为
这是关于参数
的线性方程组,用矩阵表示为
(4.4.5)
(4.4.5)称为法方程.当
线性无关,且在点集
上至多只有 n 个不同零点,则称
Haar 条件,此时(4.4.5)的解存在唯一。记(4.4.5)的解为
从而得到最小二乘拟合曲线
可以证明对 ,有
在 X 上满足
(4.4.6)
故(4.4.6)得到的
即为所求的最小二乘解.它的平方误差为
(4.4.7)
均方误差为
在最小二乘逼近中,若取 ,则 , 表示为
(4.4.8)
输入已知点个数
输入已知点个数 n
输入已知点的 X 坐标
输入已知点的 Y 坐标
此时关于系数
作为基。
程序流程图:
的法方程(4.4.5)是病态方程,通常当 n≥3 时都不直接取
开始
↓
↓
↓
↓
输出结果
程序:
#include
#include
#include
#include
float average(int n,float *x)
{int i;
float av;
av=0;
for(i=0;i
av+=*(x+i);
av=av/n;
return(av);
}
//平方和
float spfh(int n,float *x)
{int i;
float a,b;
a=0;
for(i=0;i
a+=(*(x+i))*(*(x+i));
return(a);
}
//和平方
float shpf(int n,float *x)
{int i;
float a,b;
a=0;
for(i=0;i
=a+*(x+i);
=a*a/n;
return(b);
}
//两数先相乘,再相加
float dcj(int n,float *x,float *y) {int i;
float a;
a=0;
for(i=0;i
a+=(*(x+i))*(*(y+i));
return(a);
}
//两数先相加,再相乘
float djc(int n,float *x,float *y) {int i;
float a=0,b=0;
for(i=0;i
{a=a+*(x+i);
b=b+*(y+i);
}
a=a*b/n;
return(a);
}
//系数 a
float xsa(int n,float *x,float *y)
{float a,b,c,d,e;
=spfh(n,x);
=shpf(n,x);
=dcj(n,x,y);
=djc(n,x,y);
=(c-d)/(a-b);
//printf("%f %f %f %f",a,b,c,d);
return(e);
}
float he(int n,float *y)
{int i;
float a;
a=0;
for(i=0;i
a=a+*(y+i);
return(a);
}
float xsb(int n,float *x,float *y,float a)
{ float b,c,d;
=he(n,y);
=he(n,x);
=(b-a*c)/n;
return(d);
}
void main()
{ int n,i;
float *x,*y,a,b;
printf("请输入将要输入的有效数值组数 n 的值:"); scanf("%d",&n);
x=(float*)calloc(n,sizeof(float));
if(x==NULL)
{printf("内存分配失败");
exit(1);
}
y=(float*)calloc(n,s