首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

演算法單遍掃描 vs 多遍掃描:相關係數計算公式優化原理

     編輯:程式設計疑難解答

兩種公式對比

公式一 (定義式):
r = Σ((xi - x̄)(yi - ȳ)) / sqrt(Σ(xi - x̄)² Σ(yi - ȳ)²)

公式二 (計算式/單遍掃描):
r = (nΣxiyi - ΣxiΣyi) / sqrt([nΣxi² - (Σxi)²] [nΣyi² - (Σyi)²])

為什麼公式二只需單遍掃描?

  • 公式一需要 x̄ 和 ȳ (平均值),**必須先完整掃描一次數據求和計算平均值**,第二遍才能計算分子分母。
  • 公式二利用代數變換 (展開平方、合併同類項) **消去了平均值**,僅需累加 Σxi, Σyi, Σxiyi, Σxi², Σyi² 五個累加器,**一次循環即可完成**。

代碼對比

// 公式一:兩遍
double sumX=0, sumY=0;
for (v: data) { sumX+=v.x; sumY+=v.y; }
double avgX=sumX/n, avgY=sumY/n;
double num=0, denX=0, denY=0;
for (v: data) { 
    double dx=v.x-avgX, dy=v.y-avgY;
    num+=dx*dy; denX+=dx*dx; denY+=dy*dy;
}
r = num / sqrt(denX*denY);

// 公式二:單遍
double Sx=0, Sy=0, Sxy=0, Sx2=0, Sy2=0;
for (v: data) {
    Sx+=v.x; Sy+=v.y; Sxy+=v.x*v.y; Sx2+=v.x*v.x; Sy2+=v.y*v.y;
}
r = (n*Sxy - Sx*Sy) / sqrt((n*Sx2 - Sx*Sx) * (n*Sy2 - Sy*Sy));

數值穩定性提醒

公式二對大數據量、大數值**存在災難性抵消** (減去兩個接近的大數),精度損失嚴重。工程實踐中:

  • 小規模/教學 → 公式二單遍快。
  • 大規模/高精度要求 → 公式一雙遍、Welford 單遍穩定算法、或 Kahan 求和補償。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved