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,记得勾选散点图)
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);
}