📚 C - Line of best fit | C语言实现最佳拟合线
In data science and experimental physics, finding a trend through scattered points is essential. The line of best fit, derived by linear regression, minimises the sum of squared residuals. In this article we explore how to compute this line efficiently in the C programming language, covering the underlying least‑squares method, floating‑point precision, edge cases, and a complete code walk‑through tailored to the IB Computer Science syllabus.
在数据科学与实验物理中,寻找经过散点的趋势至关重要。最佳拟合线通过线性回归得到,并最小化残差平方和。本文探讨如何用 C 语言高效计算该直线,内容涵盖最小二乘法的原理、浮点精度、边界情形,并给出完整的代码走查,贴合 IB 计算机科学课程大纲。
1. Concept of the Line of Best Fit | 最佳拟合线的概念
dependent variable x and a dependent variable y. For a set of N observed points (x₁, y₁), (x₂, y₂), … duals) as small as possible overall. This is the foundation of simple linear regression, widely used for prediction and trend analysis.
最佳拟合线描述了自变量 x 与因变量 y 之间的线性关系 y = mx + c。对于 N 个观测点 (x₁, y₁), (x₂, y₂), …, (xₙ, yₙ),最佳直线应使整体垂直距离(残差)尽可能小。这就是简单线性回归的基础,广泛用于预测和趋势分析。
2. Mathematical Foundation: Least Squares | 数学基础:最小二乘法
By differentiating E with respect to m and c and setting the derivatives to zero, we obtain the normal equations. This method is called ordinary least squares (OLS) and assumes that errors are normally distributed and independent.
目标是使误差平方和 E = Σ (yᵢ − (m xᵢ + c))² 最小化。通过对 m 和 c 分别求导并设为零,我们得到正规方程组。这种方法称为普通最小二乘法(OLS),假设误差服从正态分布且相互独立。
3. Deriving the Formulas for Slope and Intercept | 推导斜率和截距公式
Solving the normal equations yields the well‑known expressions. The slope m and intercept c can be computed directly from the sums of the data points:
m = (N · Σ(xᵢ · yᵢ) − Σxᵢ · Σyᵢ) / (N · Σ(xᵢ²) − (Σxᵢ)²)
c = (Σyᵢ − m · Σxᵢ) / N
解正规方程后得到熟悉的表达式。斜率 m 和截距 c 可直接由数据点的各项和计算得出:
m = (N · Σ(xᵢ · yᵢ) − Σxᵢ · Σyᵢ) / (N · Σ(xᵢ²) − (Σxᵢ)²)
c = (Σyᵢ − m · Σxᵢ) / N
4. Algorithm Design in Pseudocode | 算法设计与伪代码
Before writing C code, it is helpful to outline the steps:
- Initialise sums: sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0.
- For each data point (x, y), add x to sumX, y to sumY, x×y to sumXY, and x² to sumX2.
- ompute denominator = N × sumX2 − sumX × sumX. If denominator is zero, the line is vertical – handle separately.
- Calculate m = (N × sumXY − sumX × sumY) / denominator.
- Calculate c = (sumY − m × sumX) / N.
在编写 C 代码之前,先勾勒出步骤:
- 初始化累加器:sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0。
- 对每个数据点 (x, y),将 x 加入 sumX,y 加入 sumY,x×y 加入 sumXY,x² 加入 sumX2。
- 计算分母:denom = N × sumX2 − sumX × sumX。若分母为零,直线垂直——需单独处理。
- 计算 m = (N × sumXY − sumX × sumY) / denom。
- 计算 c = (sumY − m × sumX) / N。
5. Data Representation in C | C语言中的数据表示
In C, we can store the data points in parallel arrays or a struct array. For simplicity, we use two arrays double x[N] and double y[N]. All accumulators are double to avoid integer division and preserve precision. Using double minimises rounding errors when squaring small quantities.
在 C 语言中,我们可以将数据点存储在平行数组或结构体数组中。为简单起见,使用两个数组 double x[N] 和 double y[N]。所有累加器均为 double 类型,避免整数除法,并保持精度。使用 double 能在对小数进行平方时减少舍入误差。
6. Implementing the Calculation in C | 用C语言实现计算
The core function line_of_best_fit loops through the arrays, accumulates the sums, and then applies the formulas. Below is a complete implementation including input reading and formatted output.
#include <stdio.h>
void line_of_best_fit(double x[], double y[], int n, double *m, double *c) {
double sumX = 0.0, sumY = 0.0, sumXY = 0.0, sumX2 = 0.0;
for (int i = 0; i < n; i++) {
sumX += x[i];
sumY += y[i];
sumXY += x[i] * y[i];
sumX2 += x[i] * x[i];
}
double denom = n * sumX2 - sumX * sumX;
if (denom == 0.0) {
*m = 0.0; // handle vertical line separately
*c = 0.0;
return;
}
*m = (n * sumXY - sumX * sumY) / denom;
*c = (sumY - (*m) * sumX) / n;
}
int main() {
int N = 5;
double x[] = {1.0, 2.0, 3.0, 4.0, 5.0};
double y[] = {2.0, 3.0, 5.0, 4.0, 6.0};
double slope, intercept;
line_of_best_fit(x, y, N, &slope, &intercept);
printf("Line of best fit: y = %.4fx + %.4f\n", slope, intercept);
return 0;
}
核心函数 line_of_best_fit 遍历数组、累加各项和,然后套用公式。上面给出了包含输入读取与格式化输出的完整实现。
7. Handling Vertical Lines and Edge Cases | 处理垂直直线及边界情况
If all x‑ the code should detect the zero denominator and set a flag or return a distinct value. Similarly, when N < 2, the fit is undefined; the function must validate the number of points.
若所有 x 坐标相同,分母为零,这意味着直线垂直,无法用 y = mx + c 表示。此时代码应检测到分母为零并设置标志或返回特殊值。同样,当 N < 2 时拟合无定义,函数必须验证点的数量。
8. Precision, Floating‑Point Errors and Stability | 精度、浮点误差与稳定性
Accumulating many floating‑point numbers can lead to loss of significance. For large datasets, consider using compensated summation (Kahan algorithm) or computing sums in higher precision. In IB contexts, using double is sufficient, but awareness of catastrophic cancellation is expected. Subtracting two large, nearly equal terms (as in the denominator) can erode significant digits.
累加大量浮点数可能导致有效数字丢失。对于大数据集,可考虑使用补偿求和(Kahan算法)或以更高精度计算。在 IB 环境下,使用 double 足够,但应当了解灾难性抵消。分母中两个大数相减接近相等时,会损失有效数字。
9. Testing with Sample Data | 样本数据测试
Let us test the program with known coordinates. For points (1,2), (2,3), (3,5), (4,4), (5,6), the expected slope is 0.9 and intercept is 1.5. The output should be y = 0.9000x + 1.5000. Comparing with manual calculation validates the implementation.
我们使用已知坐标测试程序。对于点 (1,2), (2,3), (3,5), (4,4), (5,6),预期斜率为 0.9,截距为 1.5。输出应为 y = 0.9000x + 1.5000。与手工计算对照可验证实现。
10. Extending to Weighted Best Fit | 扩展至加权最佳拟合
When some measurements are more reliable than others, a weighted least‑squares approach is used. Each point (xᵢ, yᵢ) gets a weight wᵢ. The formulas become:
m = ( Σwᵢ · Σ(wᵢ xᵢ yᵢ) − Σ(wᵢ xᵢ) · Σ(wᵢ yᵢ) ) / ( Σwᵢ · Σ(wᵢ xᵢ²) − (Σ(wᵢ xᵢ))² )
c = ( Σ(wᵢ yᵢ) − m · Σ(wᵢ xᵢ) ) / Σwᵢ
当某些测量值更可靠时,使用加权最小二乘法。每个点 (xᵢ, yᵢ) 具有权重 wᵢ。加权后的公式如下:
m = ( Σwᵢ · Σ(wᵢ xᵢ yᵢ) − Σ(wᵢ xᵢ) · Σ(wᵢ yᵢ) ) / ( Σwᵢ · Σ(wᵢ xᵢ²) − (Σ(wᵢ xᵢ))² )
c = ( Σ(wᵢ yᵢ) − m · Σ(wᵢ xᵢ) ) / Σwᵢ
11. Performance Considerations and Optimisation | 性能考量与优化
The single‑pass algorithm runs in O(N) time, which is optimal. Memory usage is O(1) beyond the input arrays. For extremely large datasets, using float instead of double may speed up execution but at the cost of precision. Loop unrolling or vectorisation can be applied, though these are outside the scope of typical IB questions.
单遍扫描算法的时间复杂度为 O(N),已经最优。除输入数组外空间复杂度为 O(1)。对于极大数据集,使用 float 替代 double 可加速执行但会损失精度。还可应用循环展开或向量化,不过这些已超出典型 IB 考题范围。
12. IB Exam Relevance and Common Pitfalls | IB考试关联与常见易错点
In IB Computer Science Paper 2 and the IA, understanding how to translate a mathematical model into a C program is crucial. Students often forget to initialise accumulators, misuse integer arithmetic, or ignore the case of a zero denominator. Examiners look for correct data types, defensive programming, and clear logical structure. Practise deriving the formulas and tracing the code to avoid losing marks.
在 IB 计算机科学试卷二及内部评估中,懂得将数学模型转化为 C 程序至关重要。学生常忘记初始化累加器、误用整数运算,或忽略分母为零的情况。考官看重正确的数据类型、防御性编程及清晰的逻辑结构。请练习推导公式并跟踪代码,以避免失分。
Published by TutorHao | Computer Science Revision Series | aleveler.com
更多咨询请联系16621398022(同微信)

或截图后用「扫一扫 → 相册」选择本图