PHP 社區缺乏成熟數學/統計庫,主因:既有工具(R、S System、Python SciPy)已極完善,透過 exec() 調用即可。但開發原生 PHP 數學庫具教學價值,能深化對算法理解,且避免進程切換開銷,適合輕量級內嵌計算場景。
SimpleLinearRegression、MultipleRegression、ChiSquaredgetSlope(), getIntercept(), getRSquared(), getStdError())<?php
class SimpleLinearRegression {
// 輸入數據
private $x = array();
private $y = array();
private $n = 0;
// 中間結果緩存
private $sumX = null;
private $sumY = null;
private $sumXY = null;
private $sumX2 = null;
private $sumY2 = null;
// 核心統計量
private $slope = null;
private $intercept = null;
private $rSquared = null;
private $stdError = null;
public function __construct(array $x, array $y) {
if (count($x) !== count($y)) throw new InvalidArgumentException('X/Y 長度必須相等');
$this->x = $x;
$this->y = $y;
$this->n = count($x);
}
// 惰性計算中間和
private function computeSums() {
if ($this->sumX !== null) return;
$sumX = $sumY = $sumXY = $sumX2 = $sumY2 = 0;
for ($i = 0; $i < $this->n; $i++) {
$sumX += $this->x[$i];
$sumY += $this->y[$i];
$sumXY += $this->x[$i] * $this->y[$i];
$sumX2 += $this->x[$i] ** 2;
$sumY2 += $this->y[$i] ** 2;
}
$this->sumX = $sumX; $this->sumY = $sumY; $this->sumXY = $sumXY;
$this->sumX2 = $sumX2; $this->sumY2 = $sumY2;
}
private function computeCoefficients() {
if ($this->slope !== null) return;
$this->computeSums();
$denom = $this->n * $this->sumX2 - $this->sumX ** 2;
if ($denom == 0) throw new RuntimeException('X 變量無變異,無法擬合');
$this->slope = ($this->n * $this->sumXY - $this->sumX * $this->sumY) / $denom;
$this->intercept = ($this->sumY - $this->slope * $this->sumX) / $this->n;
}
public function getSlope() { $this->computeCoefficients(); return $this->slope; }
public function getIntercept() { $this->computeCoefficients(); return $this->intercept; }
public function predict($x) { return $this->getSlope() * $x + $this->getIntercept(); }
public function getRSquared() {
if ($this->rSquared !== null) return $this->rSquared;
$this->computeCoefficients();
$this->computeSums();
$ssTot = $this->sumY2 - $this->sumY ** 2 / $this->n;
$ssRes = 0;
for ($i = 0; $i < $this->n; $i++) {
$yHat = $this->predict($this->x[$i]);
$ssRes += ($this->y[$i] - $yHat) ** 2;
}
$this->rSquared = 1 - $ssRes / $ssTot;
return $this->rSquared;
}
public function getStandardError() {
if ($this->stdError !== null) return $this->stdError;
$this->getRSquared(); // 確保 ssRes 計算
$this->stdError = sqrt($ssRes / ($this->n - 2));
return $this->stdError;
}
public function toArray() {
return [
'slope' => $this->getSlope(),
'intercept' => $this->getIntercept(),
'r_squared' => $this->getRSquared(),
'std_error' => $this->getStandardError(),
'n' => $this->n
];
}
public function __toString() {
$a = $this->toArray();
return sprintf(
"Simple Linear Regression (n=%d)\nY = %.4f X + %.4f\nR² = %.4f\nStdErr = %.4f",
$a['n'], $a['slope'], $a['intercept'], $a['r_squared'], $a['std_error']
);
}
}
?>
$x = [1,2,3,4,5];
$y = [2,4,5,4,5];
$model = new SimpleLinearRegression($x, $y);
echo $model; // 友好輸出
print_r($model->toArray()); // 結構化數據
echo "X=6 預測 Y = " . $model->predict(6);
開發 PHP 數學庫非重造輪子,而是為「可嵌入、無依賴、教學友好」場景提供選擇。遵循「單一模型單一類、逆向設計、緩存中間量、豐富 Getter」原則,可構建清晰、可維護、可擴展的數學組件庫。