最小二乘法 多项式拟合 C语言实现(引用)(附echarts画图代码)

C++多阶拟合(附echarts画图代码)

细微修改,更通用

原文章 https://blog.youkuaiyun.com/sunshineacm/article/details/79069561

/*
    本实验根据数组x[], y[]列出的一组数据,用最小二乘法求它的拟合曲线。
    近似解析表达式为y = a0 + a1 * x + a2 * x^2 + a3 * x^3;(三阶)
*/
#include <stdio.h>
#include <math.h>

#define maxn 5
#define rank_ 3 //阶数

int main()
{

    // double x[maxn] = {0, 0.25, 0, 5, 0.75};
    // double y[maxn] = {1, 1.283, 1.649, 2.212, 2.178};
    double x[maxn] = {0, 5, 10, 15, 20};//, 25, 30, 35, 40, 45, 50, 55};
    double y[maxn] = {0, 1.27, 2.16, 2.86, 3.44};//, 3.87, 4.15, 4.37, 4.51, 4.58, 4.02, 4.64};

    double atemp[2 * rank_ + 1] = {0}, b[rank_ + 1] = {0}, a[rank_ + 1][rank_ + 1];
    int i, j, k;

    for (i = 0; i < maxn; i++)
    { 
        for (j = 0; j < rank_ + 1; j++)
        {
            b[j] += pow(x[i], j) * y[i];
        }

        for (j = 0; j < (2 * rank_ + 1); j++)
        {
            atemp[j] += pow(x[i], j);
        }
    }
    atemp[0] = maxn;
    for (i = 0; i < rank_ + 1; i++)
    { //构建线性方程组系数矩阵,b[]不变
        k = i;
        for (j = 0; j < rank_ + 1; j++)
            a[i][j] = atemp[k++];
    }
    //以下为高斯列主元消去法解线性方程组
    for (k = 0; k < rank_ + 1 - 1; k++)
    { //n - 1列
        int column = k;
        double mainelement = a[k][k];

        for (i = k; i < rank_ + 1; i++) //找主元素
            if (fabs(a[i][k]) > mainelement)
            {
                mainelement = fabs(a[i][k]);
                column = i;
            }
        for (j = k; j < rank_ + 1; j++)
        { //交换两行
            double atemp = a[k][j];
            a[k][j] = a[column][j];
            a[column][j] = atemp;
        }
        double btemp = b[k];
        b[k] = b[column];
        b[column] = btemp;

        for (i = k + 1; i < rank_ + 1; i++)
        { //消元过程
            double Mik = a[i][k] / a[k][k];
            for (j = k; j < rank_ + 1; j++)
                a[i][j] -= Mik * a[k][j];
            b[i] -= Mik * b[k];
        }
    }
    b[rank_ + 1 - 1] /= a[rank_ + 1 - 1][rank_ + 1 - 1]; //回代过程
    for (i = rank_ + 1 - 2; i >= 0; i--)
    {
        double sum = 0;
        for (j = i + 1; j < rank_ + 1; j++)
            sum += a[i][j] * b[j];
        b[i] = (b[i] - sum) / a[i][i];
    }
    //高斯列主元消去法结束,输出
    printf("P(x) = %f%+fx%+fx^2%+fx^3\n\n", b[0], b[1], b[2], b[3]);
    return 0;
}

#Echarts做的图(要先下echarts.min.js,记得勾选散点图)
echarts画的模拟图
html部分

<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<title>test</title>
		<meta charset="utf-8" />
		<meta name="renderer" content="webkit" />
	</head>
	<body>
		<div id="Graph" style="width: 800px;height: 500px;">123</div>
	</body>
	<script src="echarts.min.js?ver="></script>
	<script src="index.js?ver="></script>
</html>

js部分

draw();

function f1(x) {//二阶拟合
	let y = 0.230467 + 0.203691 * x - 0.002381 * x * x;
	return y;
}

function f3(x) {//三阶
	let y = 0.017839 + 0.263399 * x - 0.005216 * x * x + 0.000034 * x * x * x;
	return y;
}

function f4(x) {//二阶,数据减少为5个
	return (0.027714 + 0.259114 * x - 0.004486 * x * x) // + 0.000034 * x * x * x;
}

function draw() {

	let x = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55];
	let y = [0, 1.27, 2.16, 2.86, 3.44, 3.87, 4.15, 4.37, 4.51, 4.58, 4.02, 4.64];

	let data = [];
	let data2 = []
	let data3 = []
	let data4 = []

	for (let idx in x) {
		let a = [];
		a.push(x[idx]);
		a.push(y[idx]);
		data.push(a);


		let b = [];
		b.push(x[idx]);
		b.push(f1(x[idx]))
		data2.push(b);

		let c = [];
		c.push(x[idx]);
		c.push(f3(x[idx]))
		data3.push(c);

		let c4 = [];
		c4.push(x[idx]);
		c4.push(f4(x[idx]))
		data4.push(c4);

	}

	let option = {
		tooltip: {
			trigger: 'axis',
			axisPointer: { // 坐标轴指示器,坐标轴触发有效
				type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
			}
		},
		legend: {
			data: ['原数据', '二阶', '三阶', '二阶5数据', "5"]
		},
		xAxis: {},
		yAxis: {},
		series: [{
				symbolSize: 10,
				data: data,
				type: 'scatter',
				name: '原数据'
			},

			{
				symbolSize: 10,
				data: data2,
				type: 'scatter',
				name: '二阶'
			},

			{
				symbolSize: 10,
				data: data3,
				type: 'scatter',
				name: '三阶'
			},
			{
				symbolSize: 10,
				data: data4,
				type: 'scatter',
				name: '二阶5数据'
			},

		]
	};

	// 基于准备好的dom,初始化echarts实例
	var myChart = echarts.init(document.getElementById('Graph'));
	myChart.setOption(option);
}

### C语言实现最小二乘法多项式拟合 为了实现最小二乘法进行多项式拟合,在C语言中通常会定义一系列函数用于处理矩阵运算以及求解方程组。下面是一个简单的例子,展示了如何利用这些技术完成二次多项式拟合。 #### 定义必要的结构体和辅助函数 首先创建一个表示系数向量的数组,并编写一些基本操作如初始化、打印等功能: ```c #include <stdio.h> #include <stdlib.h> #define MAX_DEGREE 10 // 设置最大支持的多项式阶数 typedef struct { double *coefficients; // 存储多项式的各个系数 } Polynomial; // 初始化多项式对象并分配内存空间 void init_polynomial(Polynomial* p, int degree) { p->coefficients = (double*)malloc((degree + 1) * sizeof(double)); } // 打印多项式表达式 void print_polynomial(const Polynomial* p, int degree) { printf("f(x)="); for(int i=degree;i>=0;i--) { if(i != degree && p->coefficients[i] >= 0) putchar('+'); printf("%.2lfx^%d",p->coefficients[i],i); } } ``` #### 构建正规方程组并求解 接下来构建正规方程组(Normal Equation),并通过高斯消元或其他数值方法解决它得到最终的结果: ```c int fit_least_squares(Polynomial* result,int n,double x[],double y[]) { /* ...省略部分代码... */ // 计算X'X矩阵及其逆矩阵 Matrix A; invert_matrix(A); // 解决AX=B获得参数估计值 solve_linear_system(A,B,result); return SUCCESS; } ``` 请注意上述代码片段中的`Matrix`类型及相关操作并未给出具体实现细节;实际应用时需引入合适的库或自行开发相应功能[^1]。 对于更具体的场景比如嵌入式系统上的STM32单片机而言,则可以参考开源项目提供的解决方案[^2]。该项目不仅实现了基础的一次线性回归分析,还提供了完整的工程文件以便快速上手实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值