最小二乘法似合直线

今天给高个范师兄写了一个SVD分解,关于SVD的具体应用还不清楚,所以到网上看了一下,也没整太明白。偶然看到最小二乘法的原理,觉得以后可能会用的着,于是便试着写了一个简单的似合直线的。

我们在研究两个变量X,Y之间的关系时,通常可以得到一系列成对的数据(x1,y1),(x2,y2)…(xn,yn),将这些数据描绘在X-Y直角坐标系中时,若发现这些点在一条直线附近,可令这条直线的方程如下:
Y=aX+b
其中a b是任意常数,为了得到这条直线方程就要求出a b的值。
这里不深究具体的求a b的步骤,我们只要最终的计算公式就可以了。

    a0 = (∑Yi) / m - a1(∑Xi) / m
a1 
= [∑Xi Yi - (∑Xi ∑Yi)/ m] / [∑Xi2 - (∑Xi)2 / m)] 

下面是最小二乘法似合直线的源程序:

#include <stdio.h>

double k[2][3];//变量X,Y 线性方程系数k 

//∑Xi2 ∑Xi*Yi ∑Xi^2 等值
double
fsum (
double a[], double b[], int c)
{
  
double sum = 0;
  
for (int i = 0; i < c; i++)
    sum 
+= a[i] * b[i];
  
return sum;
}


//求矩阵
double
fmatrix (
int m, int n)
{
  
double matrix;
  matrix 
= k[0][m] * k[1][n] - k[0][n] * k[1][m];
  
return matrix;
}


int 
main ()
{
  
int N=3,i=0,j=0;
  
double mi[N];        //大小为1的数列,矩阵求和时匹配使用
  double x[N];    //初始化三组数据
  double y[N];
  
for(i=0; i<N; i++)
  
{
      x[i]
=i*1.0;
      y[i]
=i*2.0;
  }

  
double m1, m2, m0;

  
//求线性方程系数
  k[0][0= fsum (x, x, N);
  k[
0][1= fsum (x, mi, N);
  k[
0][2= -fsum (x, y, N);
  k[
1][0= fsum (x, mi, N);
  k[
1][1= N;
  k[
1][2= -fsum (mi, y, N);

  
//输出线性方程系数
  printf (" The modulus is: ");
  
for (i = 0; i < 2; i++)
    
{
      
for (j = 0; j < 3; j++)
    printf (
"%15lf    ", k[i][j]);
      printf(
" ");
    }


  
//线性方程矩阵m0 m1 m2
  m0 = fmatrix (01);
  m1 
= fmatrix (12);
  m2 
= fmatrix (20);
  printf (
" %lf %lf %lf ", m0, m1, m2);
  
if (m0 == 0)
    printf (
"此直线为X=%d!",x[0]);
  
else
    printf (
"The function should be: Y= %lf X %+lf ", m1 / m0, m2 / m0);
    /*
    double a1=(-k[0][2]+k[0][1]*k[1][2]/N) / (k[0][0]-k[0][1]*k[0][1]/N);
    double a0=-k[1][2]/N-a1*k[0][1]/N;
    printf("Y= %lf X+%lf/n",a1,a0);
    */
  
return 0;
}
阅读更多
换一批

没有更多推荐了,返回首页