給定 n 個已知點 (x₀,y₀)…(xₙ₋₁,yₙ₋₁),Lagrange 插值構造 n-1 次多項式:
f(x) = Σₖ₌₀ⁿ⁻¹ yₖ · Lₖ(x)
其中基函數 Lₖ(x) = Πᵢ₌₀,ᵢ≠ₖⁿ⁻¹ (x - xᵢ) / (xₖ - xᵢ)。
<?php
class Lagrange {
private $dots = [];
public function __construct(array $dots) {
// $dots = ['x' => [...], 'y' => [...]]
$this->dots = $dots;
}
private function getLk(float $x, int $k): float {
$n = count($this->dots['x']);
$omega_xk = 1.0;
$omega_x = 1.0;
for ($i = 0; $i < $n; $i++) {
if ($i !== $k) {
$omega_xk *= ($this->dots['x'][$k] - $this->dots['x'][$i]);
$omega_x *= ($x - $this->dots['x'][$i]);
}
}
return $omega_x / $omega_xk;
}
public function getY(float $x): float {
$n = count($this->dots['x']);
$sum = 0.0;
for ($k = 0; $k < $n; $k++) {
$sum += $this->dots['y'][$k] * $this->getLk($x, $k);
}
return $sum;
}
public function draw(): void {
$img = imagecreatetruecolor(500, 500);
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
$red = imagecolorallocate($img, 255, 0, 0);
imagefill($img, 0, 0, $white);
$n = count($this->dots['x']);
$maxX = max($this->dots['x']);
$step = 0.1;
$r = 4;
// 繪製已知點
for ($i = 0; $i < $n; $i++) {
$px = (int)$this->dots['x'][$i];
$py = 500 - (int)$this->dots['y'][$i]; // Y 軸翻轉
imagefilledellipse($img, $px, $py, $r, $r, $red);
}
// 繪製插值曲線
for ($x = $this->dots['x'][0] - 10; $x < $maxX + 10; $x += $step) {
$x1 = (int)$x;
$y1 = 500 - (int)$this->getY($x);
$x2 = (int)($x + $step);
$y2 = 500 - (int)$this->getY($x + $step);
imageline($img, $x1, $y1, $x2, $y2, $black);
}
header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);
}
}
// 使用示例
$points = [
'x' => [10, 30, 100, 120, 220],
'y' => [20, 40, 240, 220, 340],
];
$lag = new Lagrange($points);
$lag->draw();
500 - y 翻轉。$step = 0.1 平衡曲線平滑度與性能;生產環境可根據圖像寬度動態計算。getPolynomialCoefficients() 導出多項式系數,便於離線計算。gnuplot 或 Python Matplotlib 生成出版級圖表。Lagrange 插值原理直觀、實現簡潔,適合教學演示與小規模數據擬合。PHP 配合 GD 庫可直觀輸出圖像,但大規模或高精度場景建議轉向 SciPy/NumPy 生態。