最小二乘法曲线拟合(源代码)_用最小二乘法求拟合曲线源程序_jay_hkj的博客-程序员秘密

在已知曲线函数的情况下,对已知数据使用最小二乘法进行参数求解,从而实现曲线拟合的方法最为简便高效。

数据如下,匹配函数为 y = a0+a1*x .

0 1 2 3 4 5
x 1.5 2.5 3.5 4.5 5.5
y 4 6 8 10 12


高斯消元法的声明文件头

#ifndef GAUSSEQUATION_H
#define GAUSSEQUATION_H
#include <vector>

class GaussEquation
{
    public:
        GaussEquation();
        GaussEquation(int M,double *matrix,double *b);
        virtual ~GaussEquation();
        bool Resolve(std::vector<double>& xValue);
    protected:

    private:
        double *m_matrixA;
        int m_DIM;
        double *m_bVal;
        int SelectPivotalElement(int col); //find the row number of max value in column i;
        bool IsPrecisionZero(double aij);
        void SimplePivotalRow(int i,int j);
        void SwapRow(int i,int j);
        void RowElimination(int i,int j,int k);
};

#endif // GUASSEQUATION_H


高斯消元法的类定义源文件

#include "GaussEquation.h"
#include <cassert>
#include <cmath>
GaussEquation::GaussEquation()
{
    //ctor
}

GaussEquation::~GaussEquation()
{
    //dtor
    delete[] m_matrixA;
    delete[] m_bVal;
}


GaussEquation::GaussEquation(int M,double *matrix,double *b)
{
    m_DIM = M;
    m_matrixA = new double[M*M];
    m_bVal = new double[M];
    for(int i = 0; i <M; i++)
    {   m_bVal[i] = b[i];
        for(int j = 0; j < M; j++)
        {
        m_matrixA[i*m_DIM+j] = matrix[i*m_DIM+j];
        }
    }
}


bool
GaussEquation::Resolve(std::vector<double>& xValue)
{

    assert(static_cast<int>(xValue.size()) == m_DIM);

    for(int i = 0; i<m_DIM;i++)
    {

        int pivotRow = SelectPivotalElement(i);
        if(pivotRow != i)
        {
            SwapRow(i,pivotRow);
        }
        if(IsPrecisionZero(m_matrixA[i*m_DIM+i]))
        {
            return false;
        }

        SimplePivotalRow(i,i);

        for(int j = i + 1; j < m_DIM; j++)
        {
            RowElimination(i,j,i);
        }
    }

    m_matrixA[(m_DIM-1)*m_DIM+m_DIM-1] = m_bVal[m_DIM-1];///m_matrixA[(m_DIM-1)*m_DIM+m_DIM-1];
    for(int i =m_DIM-2;i>=0;i--)//行 i
    {
        double totalCof = 0.0;
        for(int j=i+1;j<m_DIM;j++)//列 j 
        {
            totalCof += m_matrixA[i*m_DIM+j]*m_matrixA[j*m_DIM+j];
        }
        m_matrixA[i*m_DIM +i] = (m_bVal[i]-totalCof); // 行首已经归一化 

    }

    for(int i = 0; i < m_DIM; i++)
    {
        xValue[i] = m_matrixA[i*m_DIM+i];
    }

    return true;
}


bool
GaussEquation::IsPrecisionZero(double aij)
{
    return aij<0.001&&aij>-0.001;
}


//Elimination row j by row i and start this operation from column k
void
GaussEquation::RowElimination(int r_i,int r_j,int c_k)
{
    double scale;
    scale = m_matrixA[r_j*m_DIM+c_k]/m_matrixA[r_i*m_DIM+c_k];
    for(int n=c_k;n<m_DIM;n++)
    {
        m_matrixA[r_j*m_DIM+n] -= m_matrixA[r_i*m_DIM+n]*scale;
    }
    m_bVal[r_j] -= m_bVal[r_i]*scale;
}


//
int
GaussEquation::SelectPivotalElement(int col)
{
    int r=col;
    for(int i=col+1;i<m_DIM;i++)
    {
        if (fabs(m_matrixA[r*m_DIM+col])<fabs(m_matrixA[i*m_DIM+col]))
            r = i;
    }
    return r;
}


//==Transform Ar_i,c_j to 1;
void
GaussEquation::SimplePivotalRow(int r_i,int c_j)
{
    double scale = 1.0/m_matrixA[r_i*m_DIM+c_j];

    for(int i=c_j;i<m_DIM;i++)
    {
        m_matrixA[r_i*m_DIM+i]  *= scale;
    }
	m_bVal[r_i] *= scale;
}


//==Swap row r_i with row r_j
void
GaussEquation::SwapRow(int r_i,int r_j)
{
    double a_tmp,b_tmp;
    for(int i = 0; i < m_DIM; i++)
    {
        a_tmp = m_matrixA[r_i*m_DIM + i];
        m_matrixA[r_i*m_DIM + i] = m_matrixA[r_j*m_DIM + i];
        m_matrixA[r_j*m_DIM + i] = a_tmp;
    }

    b_tmp = m_bVal[r_i];
    m_bVal[r_i] = m_bVal[r_j];
    m_bVal[r_j] = b_tmp;

}

main程序

#include <iostream>
#include <vector>
#include "GaussEquation.h"
using namespace std;
double *InputArray(double* x, int size);
double *OutputArray(double *x, double *y, int size);

int main()
{
    int size;
    vector<double> xValue(2);
    vector<double>::iterator it = xValue.begin();
    bool finished;

    cout<<"Input the number of data set:";
    cin>>size;
    //scanf("%d",&size);

    double x[size],y[size];
    for(int i = 0; i < size; i++)
    {

        cin>>x[i]>>y[i];//scanf("%f,%f",x+i,y+i);
    }

    double *A = InputArray(x,size);
    double *b = OutputArray(x,y,size);

    GaussEquation equation(2,A,b);
    delete[] A;
    delete[] b;
    finished = equation.Resolve(xValue);
    cout<<"status:"<<finished<<endl;


    cout<<"a0: "<<(*it)<<",";
    it++;
    cout<<"a1: "<<(*it)<<endl;
}

// A = aT*a
double *InputArray(double* x, int size){
//    std::vector<double> A(2*2,0);
//    std::vector<double> a(size*2,1);
    double *A = new double[2*2];
    double  *a = new double[size*2]; // a = [(1,x),...]

    A[0] = 0;
    A[1] = 0;
    A[2] = 0;
    A[3] = 0;
    for(int i = 0; i < size; i++){
        a[i*2+1] = x[i];
        a[i*2+0] = 1;
    }

    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 2; j++)
        {
            for(int k = 0; k < size; k++)
            {
            A[i*2+j] += a[k*2+i]*a[k*2+j];  //aT[i,j] = a[j,i] --> aT[i,k] = a[k,i]
            }
        }
    }
    delete[] a;
    return A;

}

// b = aT*y
double *OutputArray(double *x, double *y, int size)
{
    double *b = new double[2];
    double  *a = new double[size*2];
    b[0] = 0;
    b[1] = 0;
    // a = [(1,x),...]
    // aT[i,j] =a [j,i]
    for(int i = 0; i < size; i++){
        a[i*2+1] = x[i];
        a[i*2+0] = 1;
    }

    // b = aT*y
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < size; j++)
        {
        b[i] += a[j*2+i]*y[j];
        }
    }
    delete[] a;
    return b;

}



程序执行结果:


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jay_hkj/article/details/53229919

智能推荐

VS Code能自己编程了,GitHub推出“AI程序员”插件,根据注释自动补全代码_视学算法的博客-程序员秘密

点击上方“视学算法”,选择加&#34;星标&#34;或“置顶”重磅干货,第一时间送达明敏 发自 凹非寺量子位 报道 | 公众号 QbitAI描述出你想要执行的命令,就能生成相应的代码。现在...

django报错:django.contrib.auth.models.User.DoesNotExist: User matching query does not exist._qq_38197794的博客-程序员秘密

错误提醒File “D:\python\blog\article\views.py”, line 24, in article_createuser = User.objects.get(id=1)django.contrib.auth.models.User.DoesNotExist: User matching query does not exist.“POST /article/article-create/ HTTP/1.1” 500 77368—————————————————————

函数nameWindow_weixin_30507481的博客-程序员秘密

功能:  创建一个窗口函数原型:  voidnamedWindow(const String&amp;winname,intflags=WINDOW_AUTOSIZE);     winname:窗口的名字    flags:窗口标识,可以有如下值:      WINDOW_NORMAL设置了这个值,用户便可以改变窗口的大小(没有限制)        WIND...

allchrs代码matlab,遗传算法解非线性方程组的Matlab程序_杨松圣的博客-程序员秘密

if InfN&gt;0 || NaNN&gt;0isP='Fail';p=0;returnelseisP='True';errorReciprocal=1./x_Error;sumReciprocal=sum(errorReciprocal);p=errorReciprocal/sumReciprocal;%p:可能解所对应的染色体的概率end函数(7):按概率选择染色体函数:function ...

Intellij IDEA2019创建原生web项目并且实现Servlet_夜空中的小轩的博客-程序员秘密

1、环境要求(这里不做下载安装步骤的说明)1.java 1.8.0_812.IntelliJ IDEA 2019.2.13.Tomcat2、打开idea2019并且创建项目3、配置tomcat运行4、编写Web.xml以及创建Servlet类 &lt;!-- Servlet --&gt; &lt;servlet&gt; &...

ue4 修改3dui内容_000000000000O的博客-程序员秘密

ue4 修改3dui内容 修改text内容1修改text内容2上面的方法是对外公开某个控件,然后再蓝图中直接改控件内容另一种更好的方法时,在控件上新建public变量,控件绑定到这个变量上,由蓝图直接改变这个public变量即可修改图片为image绑定一个方法然后如果不在ui控...

随便推点

点选识别DLL/滑块识别DLL/通用验证码识别DLL/图标点选/本地识别DLL_Moon__Follow的博客-程序员秘密

背景验证码识别一直都是一个重要的话题,近日有一些公司询问 本地DLL验证码识别定制的事,可以联系QQ:【167231471】定制本地离线DLL验证码识别。另外给大家普及一下通用验证码识别和滑块缺口检测的解决方案【网易、极验、腾讯滑块】返回坐标:点击进入无限打码OCR网站,如果调用量比较大,建议购买本地验证码识别DLL。识别通用验证码如果需要识别滑块,请参考官网OCR的开发文档其它:本地DLL验证码识别如 文字点选、图标点选、OCR文字识别等请联系QQ:167231471import jsoni

kubectl基本命令_查看kubectl版本_xinheng233的博客-程序员秘密

kubectl基本命令kubectl基本命令基本信息查看项目的生命周期:创建–&gt;发布–&gt;更新–&gt;回滚–&gt;删除创建kubectl run命令发布kubectl expose命令更新kubectl set回滚kubect1 rollout删除kubectl delete金丝雀发布(Canary Release)声明式管理方法kubectl基本命令基本信息查看陈述式资源管理方法: 1.kubernetes集群管理集群资源的唯一入口是通过相应的方法调用apiserver的接口 2.

Hadoop 3.0 伪分布式安装配置教程 (基于Centos)_hadoop3.0伪分布式_mythsc的博客-程序员秘密

截止到19年,Hadoop 最新的版本已经出到 3.1.1 版本了,下面就以 该版本为例,详细分析分布式安装的步骤。Hadoop 有三种安装方式,包括:1. 单机模式2. 伪分布式模式3. 分布式模式零、准备工作准备好需要安装 Hadoop 的机器,本文使用的是 4 台 centos 机器,分别是 node1, node2, node3 和 node4,需要预先准备好 Hado...

D3 二维图表的绘制系列(三十)平行坐标系折线图_PAT-python-zjw的博客-程序员秘密

上一篇: 径向树图代码结构和初始化画布的Chart对象介绍,请先看 这里本图完整的源码地址: 这里1 图表效果2 数据name,math,chinese,english,chemistry小明,30,60,57,49小红,50,95,65,65小张,66,70,40,883 关键代码导入数据d3.csv('./data.csv', function(d){ ret...

android特有的核心模块(Linux内核层)_desaco的博客-程序员秘密

android电源管理(power manager);低内存管理器(low memory killer);匿名共享内存(Ashmem);日志(Android Logger);定时器;物理内存映射管理;android定时设备;Yaffas2文件系统;Android Paraoid网络------记录下,慢慢学习

redis的 rdb 和 aof 持久化的区别 [转]_weixin_30945039的博客-程序员秘密

aof,rdb是两种 redis持久化的机制。用于crash后,redis的恢复。rdb的特性如下:Code:fork一个进程,遍历hash table,利用copy on write,把整个db dump保存下来。save, shutdown, slave 命令会触发这个操作。粒度比较大,如果save, shutdown, slave 之前crash了,则中间的操作没办法恢复。...

推荐文章

热门文章

相关标签