C语言实现最小二乘多项式曲线拟合(附带源码)
创作时间:
作者:
@小白创作中心
C语言实现最小二乘多项式曲线拟合(附带源码)
引用
CSDN
1.
https://m.blog.csdn.net/m0_61840987/article/details/145412463
最小二乘法是一种优化算法,用于通过最小化数据点与拟合曲线之间的误差平方和来找到最佳拟合曲线。本文将详细介绍如何使用C语言实现最小二乘多项式曲线拟合,包括理论讲解、代码实现和应用示例等多个方面。
项目简介
最小二乘法是一种优化算法,用于通过最小化数据点与拟合曲线之间的误差平方和来找到最佳拟合曲线。在多项式曲线拟合中,最小二乘法通过选择一个多项式形式(例如一次、二次、三次等),来拟合给定的一组数据点。
假设我们有一组数据点 (x_1, y_1), (x_2, y_2), ..., (x_n, y_n),我们希望找到一个多项式 P(x) 来最小化如下目标函数:
通过最小化这个误差函数,我们可以得到拟合的多项式系数。
项目实现思路
- 构造目标函数:
- 假设多项式为
,其中 m 是多项式的阶数(例如一次多项式、二次多项式等)。
- 构造方程系统:
- 为了最小化误差函数,需要求解方程系统,该系统是由每个未知系数的偏导数构成的。通过求导得到的一系列方程构成了一个线性方程组。
- 解线性方程组:
- 使用矩阵方法(如高斯消元法)求解方程组,得到多项式系数。
- 输出拟合结果:
- 输出计算得到的多项式系数,并使用这些系数拟合数据点。
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// 求解线性方程组 Ax = b
// 使用高斯消元法
void gaussian_elimination(double **A, double *b, double *x, int n) {
int i, j, k;
double temp;
// 构建增广矩阵
for (i = 0; i < n; i++) {
A[i][n] = b[i];
}
// 高斯消元过程
for (i = 0; i < n; i++) {
// 寻找主元素
for (j = i + 1; j < n; j++) {
if (fabs(A[i][i]) < fabs(A[j][i])) {
for (k = 0; k <= n; k++) {
temp = A[i][k];
A[i][k] = A[j][k];
A[j][k] = temp;
}
}
}
// 消元
for (j = i + 1; j < n; j++) {
temp = A[j][i] / A[i][i];
for (k = i; k <= n; k++) {
A[j][k] -= A[i][k] * temp;
}
}
}
// 回代求解
for (i = n - 1; i >= 0; i--) {
x[i] = A[i][n] / A[i][i];
for (j = i - 1; j >= 0; j--) {
A[j][n] -= A[j][i] * x[i];
}
}
}
// 生成多项式的系数
void polynomial_fit(double *x, double *y, int n, int m, double *coefficients) {
int i, j, k;
double **A, *b;
// 为矩阵和向量分配内存
A = (double **)malloc((m + 1) * sizeof(double *));
for (i = 0; i <= m; i++) {
A[i] = (double *)malloc((m + 2) * sizeof(double)); // m+2 是因为增广矩阵
}
b = (double *)malloc((m + 1) * sizeof(double));
// 构建方程组的矩阵 A 和向量 b
for (i = 0; i <= m; i++) {
for (j = 0; j <= m; j++) {
A[i][j] = 0.0;
for (k = 0; k < n; k++) {
A[i][j] += pow(x[k], i + j);
}
}
}
for (i = 0; i <= m; i++) {
b[i] = 0.0;
for (k = 0; k < n; k++) {
b[i] += y[k] * pow(x[k], i);
}
}
// 使用高斯消元法求解系数
gaussian_elimination(A, b, coefficients, m + 1);
// 释放内存
for (i = 0; i <= m; i++) {
free(A[i]);
}
free(A);
free(b);
}
// 打印多项式系数
void print_polynomial(double *coefficients, int m) {
printf("拟合的多项式系数:\n");
for (int i = m; i >= 0; i--) {
printf("a%d = %.6f\n", i, coefficients[i]);
}
}
int main() {
// 示例数据
double x[] = {1, 2, 3, 4, 5}; // 自变量
double y[] = {2.3, 2.9, 3.1, 3.6, 5.0}; // 因变量
int n = 5; // 数据点的数量
int m = 2; // 多项式的阶数(这里选择二次多项式)
double *coefficients = (double *)malloc((m + 1) * sizeof(double));
// 求解多项式系数
polynomial_fit(x, y, n, m, coefficients);
// 打印拟合结果
print_polynomial(coefficients, m);
// 释放内存
free(coefficients);
return 0;
}
代码解读
- gaussian_elimination函数:
- 该函数使用高斯消元法来求解线性方程组。它接收矩阵 A 和向量 b,通过消元和回代步骤求解系数向量 x。
- polynomial_fit函数:
- 该函数用于根据给定的数据点 (x,y) 和指定的多项式阶数 m 来求解最小二乘法拟合的多项式系数。
- 它构建一个方程组
,其中 A 是由 x 数据生成的矩阵,b 是与 y 数据相关的向量。然后通过调用gaussian_elimination函数求解系数。
- print_polynomial函数:
- 该函数打印拟合得到的多项式系数。
- main函数:
- 在main函数中,我们定义了一个简单的样本数据集 x 和 y,并调用polynomial_fit函数来计算拟合的多项式系数。最后,通过print_polynomial打印出拟合的结果。
示例输出
假设我们有以下数据点:
x = {1, 2, 3, 4, 5}
y = {2.3, 2.9, 3.1, 3.6, 5.0}
我们选择拟合一个二次多项式。运行程序后,输出将是拟合多项式的系数:
拟合的多项式系数:
a2 = 0.225000
a1 = 0.765000
a0 = 1.340000
这意味着拟合出的多项式为:
项目总结
- 功能实现:
- 本项目通过最小二乘法实现了对给定数据点的多项式拟合。通过构建方程组并使用高斯消元法求解,我们成功得到了多项式的系数。
- 优化与扩展:
- 目前的实现仅支持二次多项式(可以通过修改阶数来适应更高阶的多项式)。
- 可以进一步优化高斯消元法,加入更高效的矩阵求解算法(例如LU分解)。
- 应用场景:
- 最小二乘法多项式拟合广泛应用于数据分析、曲线拟合、统计建模等领域。在科研、工程、金融等行业中,经常需要用这种方法来拟合实验数据或预测未来趋势。
通过本项目,我们了解了最小二乘法的基本原理,并学会了如何在 C 语言中实现该算法来进行多项式拟合。
热门推荐
甘肃张掖市之—焉支山旅游攻略
创业团队如何整合资源
《鸣潮》1.3版本十大优化来袭,玩家体验全面提升
四川电力职业技术学院:百年电力名校,培养高水平“电力工匠”
探秘臭豆腐:从发酵到烹饪的全过程揭秘
车玻璃破损理赔指南:关键步骤与注意事项全解析
上香的三支香象征着什么你知道吗 三支香的意义与传统文化解析
结题报告书中研究成果精粹的写作方法
久违上行周期!猪价今年已涨四成,后市如何演绎
地库创新设计:地坪常见材料,看这篇就够了!
浅表性胃炎饮食指南:修复胃黏膜的饮食方案
《博德之门3》MOD下载次数破亿,游戏生态持续繁荣
Excel中角度转弧度的计算公式及应用
樟树是什么植物?详解其特征与用途
隔音海绵的隔音效果如何?如何选择合适的隔音材料?
反精益创业——顶层设计与业务推演: 思维导图、拓扑图与甘特图
关于生死的20条深刻语录
三峡大坝下鱼群泛滥!百斤重的大鱼到处都是,专家为何不让捕捉?
九型人格+星座:解锁你性格的神秘代码!
哲学名家名著解读:①培根及其《工具论》
最高101米,全国只有40台!深圳消防云梯车亮相抢险现场
南医大16个学院准备就绪!药学院:培养懂医精药的药学人才
成人高考毕业证与学位证的区别及难易分析
无公害斑点叉尾鮰成鱼池塘养殖技术
汽车保险续保的最佳时机是什么?这种续保策略如何影响保险成本和保障范围?
车险购买全攻略:如何以最划算的价格买到最适合的保险
Excel横向表格筛选的多种方法与实用技巧
理性主义和经验主义的区别有什么?|理性主义 | 经验主义
电动车刹车的调整方法是什么?如何提高刹车性能?
共享打印机连接失败0x00000709怎么办?详细解决方法