最小二乘法

// test_2.cpp : Defines the entry point for the console application.
//最小二乘法

#include "stdafx.h"
#include
#include

const int n = 2;
const int m = 5;
int sgn(double x);
void LSS(double G[][n+1], int xm, int xn, double x[m], double &p, double w[m]);//LSS函数内部会修改G,x和p的值
                                                                                //该函数计算系数矩阵a[n]及误差p,系数存储在x[m]前n项中

int _tmain(int argc, _TCHAR* argv[])
{
    using namespace std;
    double temp = 0.0;
    double p = 0.0;//保存误差
    double G[m][n+1] = {0};
    double x[m] = {0.1, 0.2, 0.3, 0.4, 0.5};//x[n]同时存储最终结果a[n]
    double w[m] = {0.0};

    //给G[m][n+1]赋值
    for(int i = 0; i < m; i++)
    {
        G[i][0] = 1.0;
        G[i][1] = x[i];
    }
    //将y值写入G[m][n+1]最后一列
    G[0][n] = 5.1234;
    G[1][n] = 5.3057;
    G[2][n] = 5.5678;
    G[3][n] = 5.9378;
    G[4][n] = 6.4370;
    //调用最小二乘函数
    LSS(G, m, n, x, p, w);

    //4 输出结果
    //输出系数
    cout << "系数为:/n";
    for(int i = 0; i < n; i++)
    {
        cout << "a" << i << " = " << x[i] << endl;
    }

    //输出误差
    cout << "/n误差为 " << p << endl;

    return 0;
}

 

void LSS(double G[][n+1], int xm, int xn, double x[m], double &p, double w[m])
{
    double b = 0.0;//保存二范数
    double B = 0.0;
    double t = 0.0;
    double temp = 0.0;
    //double w[m] = {0.0};//这里不能是xm,这样不好!!!

    //最小二乘算法
    //1
    for(int k = 0; k < xn; k++)
    {
        //1.1 形成矩阵Qk
        temp = 0.0;
        for(int i = k; i < xm; i++)
            temp += G[i][k] * G[i][k];
        b = -sgn(G[k][k]) * sqrt(temp);
        w[k] = G[k][k] - b;
        for(int j = k+1; j < xm; j++)
            w[j] = G[j][k];
        B = b * w[k];
        //1.2 变换Gk-1到Gk
        G[k][k] = b;
        for(int j = k+1; j < xn+1; j++)
        {   
            temp = 0.0;
            for(int i = k; i < xm; i++)
                temp += w[i] * G[i][j];
            t = temp / B;
            for(int i = k; i < xm; i++)
            G[i][j] += t * w[i];
        }
    }

    //2 解三角方程Rx=h1
    x[xn-1] = G[xn-1][xn] / G[xn-1][xn-1];
    for(int i = xn-1; i >= 0; i--)
    {
        temp = 0.0;
        for(int j = i+1; j < xn; j++)
            temp += G[i][j] * x[j];
        x[i] = (G[i][xn] - temp) / G[i][i];
    }

    //3 计算误差E2
    for(int i = xn; i < xm; i++)
        p += G[i][xn] * G[i][xn];
}

 

int sgn(double x)
{
    if (x>0) return(1);    //返回出口1:如果键盘输入正数,则返回1
    if (x<0) return(-1);   //返回出口2:如果键盘输入负数,则返回-1
    return(0);             //返回出口3:如果键盘输入0,   则返回0
}

 

最小二乘法的算法原理见《计算方法教程(第二版)》 凌永祥、陈明奎 西安交通大学出版社 2005年4月第2版 P123

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值