国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C語言編程:最小二乘法擬合直線

這篇具有很好參考價(jià)值的文章主要介紹了C語言編程:最小二乘法擬合直線。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

本文研究通過C語言實(shí)現(xiàn)最小二乘法擬合直線。

1 引入

最小二乘法,簡單來說就是根據(jù)一組觀測得到的數(shù)值,尋找一個函數(shù),使得函數(shù)與觀測點(diǎn)的誤差的平方和達(dá)到最小。在工程實(shí)踐中,這個函數(shù)通常是比較簡單的,例如一次函數(shù)或二次函數(shù)。

汽車上的毫米波雷達(dá)可以探測到其他目標(biāo)車輛,通過最小二乘法擬合目標(biāo)車輛歷史點(diǎn),可以簡單地預(yù)測目標(biāo)汽車未來的走向。

后文會推導(dǎo)最小二乘法擬合直線,并通過C語言實(shí)現(xiàn),最后進(jìn)行簡單的驗(yàn)證。對于二次及更高次多項(xiàng)式的擬合,采用類似的方法。

2 公式推導(dǎo)

作為工程應(yīng)用,推導(dǎo)公式不需要像數(shù)學(xué)上的那么抽象,只需要針對當(dāng)前需求推導(dǎo)即可。

首先,需要擬合的方程為一次函數(shù):

y = a x + b y = ax + b y=ax+b

并且已知n個觀測點(diǎn):

( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . ( x n , y n ) (x_{1}, y_{1}),(x_{2}, y_{2}),...(x_{n}, y_{n}) (x1?,y1?),(x2?,y2?),...(xn?,yn?)
則擬合的誤差的平方和為:
E ( a , b ) = ∑ i = 1 n ( a x i + b ? y i ) 2 E(a,b)=\sum_{i=1}^n\left({{}}a{{x}}{}_{{i}}+b-{{y}}{}_{{i}}\right)^2 E(a,b)=i=1n?(axi?+b?yi?)2

注意,x和y是已知量,該函數(shù)是關(guān)于a和b的二元函數(shù)。目標(biāo)是求誤差的最小值,因此需要分別對a和b求偏導(dǎo)數(shù):
? E ? a = ∑ i = 1 n 2 ? ( a x i + b ? y i ) ? x i = 2 ∑ i = 1 n ( a x i 2 + b x i ? y i x i ) \frac{\partial E}{\partial a}=\sum_{i=1}^n{2\cdot\left(a{{x}}{}_{{i}}+b-{{y}}{}_{{i}}\right)}\cdot{{x}}{}_{{i}}=2\sum_{i=1}^n{\left(a{{x}}_{{i}}^{{2}}+b{{x}}{}_{{i}}-{{y}}{}_{{i}}{{x}}{}_{{i}}\right)} ?a?E?=i=1n?2?(axi?+b?yi?)?xi?=2i=1n?(axi2?+bxi??yi?xi?) ? ? E ? b = ∑ i = 1 n 2 ? ( a x i + b ? y i ) = 2 ∑ i = 1 n ( a x i + b ? y i ) \:\frac{\partial E}{\partial b}=\sum_{i=1}^n{2\cdot\left(a{{x}}{}_{{i}}+b-{{y}}{}_{{i}}\right)}=2\sum_{i=1}^n\left(a{{x}}{}_{{i}}+b-{{y}}{}_{{i}}\right) ?b?E?=i=1n?2?(axi?+b?yi?)=2i=1n?(axi?+b?yi?)

對偏導(dǎo)數(shù)取值為0,可以得到線性方程組:
a ∑ i = 1 n x i 2 ? + b ∑ i = 1 n x i ? = ∑ i = 1 n y i x i a\sum_{i=1}^n{{{x}}_{{i}}^{{2}}}\:+b\sum_{i=1}^n{{x}}{}_{{i}}\:=\sum_{i=1}^n{{y}}{}_{{i}}{{x}}{}_{{i}} ai=1n?xi2?+bi=1n?xi?=i=1n?yi?xi? a ∑ i = 1 n x i ? + ? b n ? = ∑ i = 1 n y i a\sum_{i=1}^n{{x}}{}_{{i}}\:+\:bn_{{}}\:=\sum_{i=1}^n{{y}}{}_{{i}}{{}} ai=1n?xi?+bn?=i=1n?yi?

求解方程組可以用克拉默法則:
D = ? ∣ ∑ i = 1 n x i 2 ∑ i = 1 n x i ∑ i = 1 n x i n ∣ ? = ? n ∑ i = 1 n x i 2 ? ? ? ( ∑ i = 1 n x i ) 2 D=\:\left|\begin{matrix}{\sum_{i=1}^n{{{x}}_{{i}}^{{2}}}{}} & {\sum_{i=1}^n{{{x}}_{{i}}^{{}}}{}} \\ {\sum_{i=1}^n{{{x}}_{{i}}^{{}}}{}} & n\end{matrix}\right|\:=\:n\sum_{i=1}^n{{x}}_{{i}}^{{2}}\:-\:\left(\sum_{i=1}^n{{x}}_{{i}}^{}\right)^2 D= ?i=1n?xi2?i=1n?xi??i=1n?xi?n? ?=ni=1n?xi2??(i=1n?xi?)2 D a = ? ∣ ∑ i = 1 n x i y i ∑ i = 1 n x i ∑ i = 1 n y i n ∣ ? = ? n ∑ i = 1 n x i y i ? ? ? ∑ i = 1 n x i ∑ i = 1 n y i {{D}}{}_{{a}}=\:\left|\begin{matrix}{\sum_{i=1}^n{{{{x{}}{}_{{i}}y}}_{{i}}}{}} & {\sum_{i=1}^n{{{x}}_{{i}}^{{}}}{}} \\ {\sum_{i=1}^n{{y{}}_{{i}}^{{}}}{}} & n\end{matrix}\right|\:=\:n\sum_{i=1}^n{{{x{}}{}_{{i}}y}}_{{i}}^{{}}\:-\:\sum_{i=1}^n{x{}}{}_{{i}}\sum_{i=1}^n{y{}}_{{i}}^{{}} Da?= ?i=1n?xi?yi?i=1n?yi??i=1n?xi?n? ?=ni=1n?xi?yi??i=1n?xi?i=1n?yi? D b = ? ∣ ∑ i = 1 n x i 2 ∑ i = 1 n x i y i ∑ i = 1 n x i ∑ i = 1 n y i ∣ ? = ? ∑ i = 1 n x i 2 ? ∑ i = 1 n y i ? ? ? ∑ i = 1 n x i ∑ i = 1 n x i y i {{D}}{}_{}=\:\left|\begin{matrix}{\sum_{i=1}^n{{{x}}_{{i}}^{{2}}}{}} & {\sum_{i=1}^n{{{{x{}}{}_{{i}}y}}_{{i}}^{{}}}{}} \\ {\sum_{i=1}^n{{{x}}_{{i}}^{{}}}{}} & \sum_{i=1}^n{{y}}{}_{{i}}\end{matrix}\right|\:=\:\sum_{i=1}^n{{x}}_{{i}}^{{2}}\:\sum_{i=1}^n{{y}}{}_{{i}}\:-\:\sum_{i=1}^n{{x}}_{{i}}^{{}}\sum_{i=1}^n{{{x{}}{}_{{i}}{y{}}{}_{{i}}}} Db?= ?i=1n?xi2?i=1n?xi??i=1n?xi?yi?i=1n?yi?? ?=i=1n?xi2?i=1n?yi??i=1n?xi?i=1n?xi?yi?

可以求得a和b:
a ? = ? D a D ? = ? n ∑ x i y i ? ∑ x i ∑ y i n ∑ x i 2 ? ( ∑ x i ) 2 a\:=\:\frac{{{D}}{}_{{a}}}{D}\:=\:\frac{n\sum{{{x}}{}_{{i}}}{{y}}{}_{{i}}-\sum{{{x}}{}_{{i}}}\sum{{y{}}{}_{{i}}}}{n\sum{{x}}_{{i}}^{{2}}-\left(\sum{{x}}{}_{{i}}\right)^2} a=DDa??=nxi2??(xi?)2nxi?yi??xi?yi?? b ? = ? D b D ? = ? ∑ x i 2 ∑ y i ? ∑ x i ∑ x i y i n ∑ x i 2 ? ( ∑ x i ) 2 b\:=\:\frac{{{D}}{}_{b{}}}{D}\:=\:\frac{\sum{{x}}_{{i}}^{{2}}{{}}{}_{{}}\sum{{y{}}{}_{{i}}}-\sum{{{x}}{}_{{i}}}\sum{{{{x}}{}_{{i}}y{}}{}_{{i}}}}{n\sum{{x}}_{{i}}^{{2}}-\left(\sum{{x}}{}_{{i}}\right)^2} b=DDb??=nxi2??(xi?)2xi2??yi??xi?xi?yi??

3 C語言代碼實(shí)現(xiàn)

1)首先設(shè)計(jì)頭文件polyfit_types.h,用于定義一些基本類型和結(jié)構(gòu)體;

//polyfit_types.h
#ifndef POLYFIT_TYPES_H
#define POLYFIT_TYPES_H

typedef signed char int8;
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
typedef int int32;
typedef unsigned int uint32;
typedef float float32;

typedef struct POINT_TAG
{
	float32 x_f32;
	float32 y_f32;
}POINT_TYPE;

typedef struct LINE_TAG
{
	float32 a_f32;
	float32 b_f32;
}LINE_TYPE;

#endif

這里先定義一些基本類型,比如uint8,float32等。接著定義兩個結(jié)構(gòu)體:點(diǎn)和直線。點(diǎn)結(jié)構(gòu)體的成員是點(diǎn)的x和y坐標(biāo),直線結(jié)構(gòu)體的成員是直線的系數(shù)a和b。

2)設(shè)計(jì)頭文件polyfit.h;

//polyfit.h
#ifndef POLYFIT_H
#define POLYFIT_H

//Include
#include "polyfit_types.h"

//Define
#define EPS 0.000001F
#define OK  1U
#define NOK 0U

//Function
uint8 polyfit(const POINT_TYPE* points_vs, const uint8 point_number_u8, LINE_TYPE* line_s, float32* square_error_f32);

#endif

頭文件首先包含了type頭文件。接著是宏定義EPS表示一個極小值,用于浮點(diǎn)數(shù)相等比較。然后就是函數(shù)polyfit的聲明,函數(shù)的前兩個參數(shù)是輸入的點(diǎn)的數(shù)組和點(diǎn)的數(shù)量,后兩個參數(shù)表示輸出的直線和殘差的平方和。

3)設(shè)計(jì)C文件polyfit.c,是實(shí)現(xiàn)算法的核心代碼;

//polyfit.c
#include <math.h>
#include <string.h>
#include "polyfit.h"

//Function
uint8 polyfit(const POINT_TYPE* points_vs, const uint8 point_number_u8, LINE_TYPE* line_s, float32* square_error_f32)
{
	//var
	float32 sum_x_f32  = 0.0F;
	float32 sum_xy_f32 = 0.0F;
	float32 sum_x2_f32 = 0.0F;
	float32 sum_y_f32  = 0.0F;

	float32 xi = 0.0F;
	float32 yi = 0.0F;	

	float32 Det_f32   = 0.0F;
	float32 Det_a_f32 = 0.0F;
	float32 Det_b_f32 = 0.0F;

	float32 Err = 0.0F;

	uint8 index_u8;

	//initialize
	*square_error_f32 = 0.0F;
	memset(line_s, 0.0F, sizeof(LINE_TYPE));

	//calculate sum
	for (index_u8 = 0U; index_u8 < point_number_u8; index_u8++)
	{
		xi = points_vs[index_u8].x_f32;
		yi = points_vs[index_u8].y_f32;

		sum_x_f32  += xi;
		sum_xy_f32 += xi * yi;
		sum_x2_f32 += xi * xi;
		sum_y_f32  += yi;
	}

	//calculate determinant
	Det_f32   = point_number_u8 * sum_x2_f32 - sum_x_f32 * sum_x_f32;
	Det_a_f32 = point_number_u8 * sum_xy_f32 - sum_x_f32 * sum_y_f32;
	Det_b_f32 = sum_x2_f32      * sum_y_f32  - sum_x_f32 * sum_xy_f32;

	//determine if Det_f32 is 0
	if (fabsf(Det_f32) < EPS)
	{
		return NOK;
	}

	//calculate coefficient
	line_s->a_f32 = Det_a_f32 / Det_f32;
	line_s->b_f32 = Det_b_f32 / Det_f32;

	//calculate sum of square error
	for (index_u8 = 0U; index_u8 < point_number_u8; index_u8++)
	{
		xi = points_vs[index_u8].x_f32;
		yi = points_vs[index_u8].y_f32;

		Err = yi - (line_s->a_f32 * xi + line_s->b_f32);
		*square_error_f32 += Err * Err;
	}

	return OK;
}

代碼中,首先定義局部變量,并初始化輸出參數(shù)。接著,按照公式計(jì)算三個行列式,并判斷D是否為0,如果為零就停止計(jì)算并返回。最后通過克拉默法則計(jì)算系數(shù),以及根據(jù)算出的直線計(jì)算殘差的平方和。

4 測試驗(yàn)證

在主函數(shù)里可以簡單寫一段測試代碼,驗(yàn)證一下是否正確。

1)參考某百科,假設(shè)輸入4個點(diǎn)為(1,6),(2,5),(3,7),(4,10),測試代碼如下;

#include <stdio.h>
#include "polyfit.h"

int main()
{
	POINT_TYPE point_vs[4];
	point_vs[0].x_f32 = 1.0F; point_vs[0].y_f32 = 6.0F;
	point_vs[1].x_f32 = 2.0F; point_vs[1].y_f32 = 5.0F;
	point_vs[2].x_f32 = 3.0F; point_vs[2].y_f32 = 7.0F;
	point_vs[3].x_f32 = 4.0F; point_vs[3].y_f32 = 10.0F;

	LINE_TYPE line_s;	
	float32 square_error_f32;
	uint8 retVal;

	retVal = polyfit(point_vs, 4U, &line_s, &square_error_f32);

	printf("retVal = %d , a = %f , b = %f , err = %f \r\n", retVal, line_s.a_f32, line_s.b_f32, square_error_f32);
}

打印出來的結(jié)果為:

C語言編程:最小二乘法擬合直線,c語言,最小二乘法,算法

這表示擬合的直線方程為:

y = 1.4 x + 3.5 y = 1.4x + 3.5 y=1.4x+3.5

繪圖出來的結(jié)果是:
C語言編程:最小二乘法擬合直線,c語言,最小二乘法,算法

2)如果輸入的4個點(diǎn)是(1,6),(1,5),(1,7),(1,10),即四個點(diǎn)在一條垂直于x軸的直線上,這時(shí)行列式D=0,就無法得出擬合結(jié)果:

#include <stdio.h>
#include "polyfit.h"

int main()
{
	POINT_TYPE point_vs[4];

	point_vs[0].x_f32 = 1.0F; point_vs[0].y_f32 = 6.0F;
	point_vs[1].x_f32 = 1.0F; point_vs[1].y_f32 = 5.0F;
	point_vs[2].x_f32 = 1.0F; point_vs[2].y_f32 = 7.0F;
	point_vs[3].x_f32 = 1.0F; point_vs[3].y_f32 = 10.0F;

	LINE_TYPE line_s;	
	float32 square_error_f32;
	uint8 retVal;

	retVal = polyfit(point_vs, 4U, &line_s, &square_error_f32);

	printf("a = %f , b = %f , err = %f \r\n", line_s.a_f32, line_s.b_f32, square_error_f32);
}

打印出來的結(jié)果為:

C語言編程:最小二乘法擬合直線,c語言,最小二乘法,算法

5 總結(jié)

本文本文研究通過C語言實(shí)現(xiàn)最小二乘法擬合直線。在工程應(yīng)用中,一次和二次多項(xiàng)式的擬合用的比較多。二次多項(xiàng)式擬合可以參考一次的推導(dǎo)過程和編程過程,需要求解三階行列式求解三個系數(shù)。

>>返回個人博客總目錄文章來源地址http://www.zghlxwxcb.cn/news/detail-651888.html

到了這里,關(guān)于C語言編程:最小二乘法擬合直線的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 數(shù)值分析——曲線擬合的最小二乘法

    數(shù)值分析——曲線擬合的最小二乘法

    擬合曲線定義:求近似函數(shù) φ(x), 使之 “最好” 的逼近f(x) ,無需滿足插值原則. 這就是曲線擬合問題。 (時(shí)間緊迫直接看例子就行,智慧交通專業(yè)的補(bǔ)修課,可能理論學(xué)的不那么深入,主要是方法。) 超定方程組 是指方程個數(shù)大于未知量個數(shù)的方程組 。 最小二乘解 : 對于

    2024年02月09日
    瀏覽(20)
  • Matlab 最小二乘法 擬合平面 (PCL PCA擬合平面)

    Matlab 最小二乘法 擬合平面 (PCL PCA擬合平面)

    最小二乘法 擬合平面是我們最常用的擬合平面的方法,但是有特殊的情況是用這種方法是不能擬合的,后續(xù)會加上這種擬合方法(RANSAC)。 matlab 最小二乘擬合平面(方法一) - 灰信網(wǎng)(軟件開發(fā)博客聚合) 平面方程:Ax+By+Cz+D=0; ? 1、隨機(jī)出來一些離散的點(diǎn) ?? 2、將其寫成

    2024年02月16日
    瀏覽(24)
  • 最小二乘法的幾種擬合函數(shù)

    目錄 1.最小二乘法的原理和解決的問題 2.最小二乘法的公式解法 2.1? 擬合h(x)?= a * x 2.2 擬合 h(x) = a0 + a1*x 2.3擬合 h(x) = a0 + a1 *x + a3 * x^3 ?因?yàn)椴捎镁仃嚪▉磉M(jìn)行最小二乘法的函數(shù)擬合時(shí),會出現(xiàn)系數(shù)矩陣的逆矩陣不存在的情況有一定的局限性,所以本篇對公式法進(jìn)行簡單說明

    2024年02月13日
    瀏覽(19)
  • 【Matlab】最小二乘法擬合多項(xiàng)式

    【Matlab】最小二乘法擬合多項(xiàng)式

    在最近的電機(jī)項(xiàng)目中,有遇到有傳感器數(shù)據(jù)并不線性的問題,然后想要用最小二乘法做個曲線擬合,反過來去校準(zhǔn)不線性的傳感器的數(shù)據(jù),因此記錄一下使用最小二乘法來擬合多項(xiàng)式的曲線的步驟。本篇從最小二乘法的原始公式入手編寫M文件,目的是方便使用單片機(jī)實(shí)現(xiàn),或

    2023年04月22日
    瀏覽(24)
  • 數(shù)值計(jì)算大作業(yè):最小二乘法擬合(Matlab實(shí)現(xiàn))

    數(shù)值計(jì)算大作業(yè):最小二乘法擬合(Matlab實(shí)現(xiàn))

    ? ? 作為研究生的入門課,數(shù)值計(jì)算的大作業(yè)算是所有研究生開學(xué)的重要編程作業(yè)。 ? ? ?我把最小二乘算法在MATLAB中整合成了一個M函數(shù)文件least square fitting.m,直線擬合函數(shù)lsf_linear.m,以及拋物線擬合函數(shù)lsf_parabolic.m。程序放在文章最后了,需要的同學(xué)自取。下文為作業(yè)詳

    2024年02月07日
    瀏覽(25)
  • PCL點(diǎn)云處理之最小二乘空間直線擬合(3D) (二百零二)

    PCL點(diǎn)云處理之最小二乘空間直線擬合(3D) (二百零二)

    對于空間中的這樣一組點(diǎn):大致呈直線分布,散亂分布在直線左右, 我們可采用最小二乘方法擬合直線,更進(jìn)一步地,可以通過點(diǎn)到直線的投影,最終得到一組嚴(yán)格呈直線分布的點(diǎn),同時(shí),這個結(jié)果也可以驗(yàn)證最小二乘擬合得到的直線參數(shù)是否正確,使用下面的代碼可以得到

    2024年02月12日
    瀏覽(23)
  • Open3D點(diǎn)云數(shù)據(jù)處理(二十):最小二乘直線擬合(三維)

    專欄目錄:Open3D點(diǎn)云數(shù)據(jù)處理(Python) 最小二乘三維直線擬合的原理是通過最小化數(shù)據(jù)點(diǎn)到直線距離的平方和,找到最優(yōu)的直線模型來擬合給定數(shù)據(jù)集。這個距離是指數(shù)據(jù)點(diǎn)到直線的垂線距離。 三維直線通常表示為兩個平面的交線,形如 { A

    2024年02月12日
    瀏覽(68)
  • 最短路徑算法的編程與實(shí)現(xiàn) C語言

    最短路徑算法的編程與實(shí)現(xiàn) C語言

    1.掌握最短路徑算法的基本原理及編程實(shí)現(xiàn); operating system version:Win11 CPU instruction set: ?x64 Integrated Development Environment:Viusal Studio 2022 1)建立一張圖,選擇一種存儲結(jié)構(gòu)(鄰接矩陣或鄰接表)初始化該圖; 2)用Dijkstra算法實(shí)現(xiàn)點(diǎn)與點(diǎn)之間的最短路徑。 1) 實(shí)現(xiàn)圖的兩種表示方法;

    2024年02月11日
    瀏覽(21)
  • PCL點(diǎn)云處理之最小二乘直線擬合(2D| 方法2)(?親測可用?)(二百零一)

    PCL點(diǎn)云處理之最小二乘直線擬合(2D| 方法2)(?親測可用?)(二百零一)

    在二百章中,我們介紹了一種最小二乘擬合直線點(diǎn)云(2D)的方法,可以獲取直線方程系數(shù)k,b,這里介紹另一種擬合直線點(diǎn)云的方法,更為簡單方便,結(jié)果與前者一致,主要內(nèi)容直接復(fù)制代碼使用即可,原理簡單看代碼即可,下面是具體的實(shí)現(xiàn)和擬合結(jié)果展示 離散點(diǎn)云中擬合規(guī)

    2024年02月16日
    瀏覽(97)
  • 掌握Go語言:Go語言遞歸函數(shù),解密編程之謎,探索算法的奧秘?。?7)

    遞歸函數(shù)是指在函數(shù)內(nèi)部調(diào)用自身的函數(shù)。在Go語言中,遞歸函數(shù)使用起來非常方便,但需要注意遞歸的終止條件,以避免無限循環(huán)。 Go語言遞歸函數(shù)的使用方法 在Go語言中,編寫遞歸函數(shù)的基本步驟如下: 上述三點(diǎn)內(nèi)容詳細(xì)解釋如下: 定義一個函數(shù),函數(shù)內(nèi)部調(diào)用自身 :

    2024年04月15日
    瀏覽(102)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包