首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 最小平方法直線擬合:Y=a0+a1X 與 Y=aX 實作

     編輯:VC 教學

前言

最小平方法是資料擬合最基礎的演算法。本文提供兩個 MFC 就緒函式:linearReg_Y_a0_a1X 解算截距 a0 與斜率 a1,linearReg_Y_aX 解算通過原點的斜率 a,皆使用 CArray<double,double> 作為輸入容器。

數學基礎

對資料點 (xi, yi),最小化誤差平方和 Σ(yi - (a0 + a1 xi))^2,對 a0, a1 求偏導數為零,得正規方程:

a1 = (Σxi yi - n x̄ ȳ) / (Σxi^2 - n x̄^2)
a0 = ȳ - a1 x̄

通過原點模型 y = a x 僅需最小化 Σ(yi - a xi)^2,解為:

a = Σxi yi / Σxi^2

函式實作

1. Y = a0 + a1 X

void linearReg_Y_a0_a1X(double& a0, double& a1,
                        const CArray<double,double>& X,
                        const CArray<double,double>& Y)
{
    double sumXiYi = 0, sumXi = 0, sumYi = 0, sumXi2 = 0;
    INT_PTR n = X.GetSize();
    for (INT_PTR i = 0; i < n; ++i) {
        sumXiYi += X[i] * Y[i];
        sumXi   += X[i];
        sumYi   += Y[i];
        sumXi2  += X[i] * X[i];
    }
    double xAvg = sumXi / n;
    double yAvg = sumYi / n;

    a1 = (sumXiYi - n * xAvg * yAvg) / (sumXi2 - n * xAvg * xAvg);
    a0 = yAvg - a1 * xAvg;
}

2. Y = a X

void linearReg_Y_aX(double& a,
                    const CArray<double,double>& X,
                    const CArray<double,double>& Y)
{
    double sumXiYi = 0, sumXi2 = 0;
    INT_PTR n = X.GetSize();
    for (INT_PTR i = 0; i < n; ++i) {
        sumXiYi += X[i] * Y[i];
        sumXi2  += X[i] * X[i];
    }
    a = sumXiYi / sumXi2;
}

使用範例

CArray<double,double> X, Y;
X.Add(1.0); Y.Add(2.1);
X.Add(2.0); Y.Add(3.9);
X.Add(3.0); Y.Add(6.2);
X.Add(4.0); Y.Add(7.8);

double a0, a1;
linearReg_Y_a0_a1X(a0, a1, X, Y);
// a0 ≈ 0.15, a1 ≈ 1.95

double a;
linearReg_Y_aX(a, X, Y);
// a ≈ 2.05

擴充建議

  • 加入決定係數 R^2 計算,評估擬合優度。
  • 支援加權最小平方法(傳入權重陣列)。
  • 使用 std::vector<double> 取代 CArray 以跨平台。
  • 大量資料時考慮數值穩定性(如 QR 分解),避免減法抵銷誤差。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved