-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathFitPowerLaw6.html
120 lines (109 loc) · 4 KB
/
FitPowerLaw6.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Power Law Fit with Chart.js</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<canvas id="myChart" width="400" height="400"></canvas>
<script>
function leastSquaresPowerLawFit(xData, yData) {
if (xData.length !== yData.length) {
throw new Error('xData and yData must have the same length.');
}
const n = xData.length;
let sumLogX = 0, sumLogY = 0, sumLogXLogY = 0, sumLogX2 = 0;
for (let i = 0; i < n; i++) {
const logX = Math.log(xData[i]);
const logY = Math.log(yData[i]);
sumLogX += logX;
sumLogY += logY;
sumLogXLogY += logX * logY;
sumLogX2 += logX * logX;
}
const numeratorB = n * sumLogXLogY - sumLogX * sumLogY;
const denominatorB = n * sumLogX2 - sumLogX * sumLogX;
const b = numeratorB / denominatorB;
const lnA = (sumLogY - b * sumLogX) / n;
const a = Math.exp(lnA);
return { a, b };
}
// 示例数据点
const data = [
{ H: 1, q: 2 },
{ H: 2, q: 4 },
{ H: 3, q: 9 },
{ H: 4, q: 16 },
{ H: 5, q: 25 }
];
// 提取 x 和 y 数据
const xData = data.map(item => item.H);
const yData = data.map(item => item.q);
// 拟合数据
const { a, b } = leastSquaresPowerLawFit(xData, yData);
console.log(`拟合结果: a=${a}, b=${b}`);
// 显示拟合结果
document.body.innerHTML += `<p>拟合结果: a=${a.toFixed(2)}, b=${b.toFixed(2)}</p>`;
// 销毁之前的图表实例(如果有)
let myChart;
if (myChart) {
myChart.destroy();
}
// 生成拟合曲线的数据点
const fitXData = Array.from({ length: 20 }, (_, i) => 1 + i * (5 - 1) / 19);
const fitYData = fitXData.map(x => a * Math.pow(x, b));
// 创建图表
const ctx = document.getElementById('myChart').getContext('2d');
myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
label: '实测数据点',
data: data.map(item => ({ x: item.H, y: item.q })),
type: 'scatter',
borderColor: 'Red',
showLine: false,
pointRadius: 5
},
{
label: `q = ${a.toFixed(2)}H^${b.toFixed(2)} l/h`,
data: fitXData.map((x, i) => ({ x, y: fitYData[i] })),
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 2,
pointRadius: 0 // 设置点的半径为 0,不显示点
}
]
},
options: {
scales: {
x: {
type: 'linear',
position: 'bottom',
beginAtZero: true,
title: {
display: true,
text: '工作压力 H(m)'
}
},
y: {
type: 'linear',
beginAtZero: true,
title: {
display: true,
text: '流量 q (l/h)'
}
}
},
elements: {
line: {
tension: 0.1 // 0 去除曲线的平滑效果,使曲线为折线
}
}
}
});
</script>
</body>
</html>