SOR 是 Gauss-Seidel (GS) 的加速版。GS 迭代公式:
x_i^(k+1) = (1/a_ii) * (b_i - Σ_{ji} a_ij x_j^(k))
引入松弛因子 ω (0<ω<2):
x_i^(k+1) = (1-ω)x_i^(k) + ω * [GS 更新值]
ω>1 為超松弛,可加速收斂;最優 ω 需實驗確定(本題取 1.4)。
#define N 9
#define OMEGA 1.4
double a[N+1][N+1] = { /* 9x9 係數矩陣,下標從 1 開始 */ };
double b[N+1] = { /* 常數項 */ };
double x[N+1][N+1] = {0}; // x[i][k] 存第 k 次迭代的第 i 個分量
for (int k=1; k<=9; ++k) { // 迭代 9 次
for (int i=1; i<=N; ++i) {
double sum1=0, sum2=0;
for (int j=1; j

1-based 需統一,避免越界。||Ax-b|| < ε 作為停止條件。為提高數值穩定性,每列選擇絕對值最大元素作主元,交換行,消去為上三角矩陣,再回代求解。
double a[N+1][N+2]; // 增廣矩陣 [A|b]
// 列主元選取與行交換
for (int j=1; j<=N-1; ++j) {
int p = j;
for (int i=j+1; i<=N; ++i)
if (fabs(a[i][j]) > fabs(a[p][j])) p = i;
if (p != j) swap_rows(a, j, p, j, N+1); // 從第 j 列開始交換
// 消去
for (int i=j+1; i<=N; ++i) {
double factor = a[i][j] / a[j][j];
for (int k=j+1; k<=N+1; ++k) // 關鍵:k 從 j+1 開始!
a[i][k] -= factor * a[j][k];
}
}
// 回代
x[N] = a[N][N+1] / a[N][N];
for (int i=N-1; i>=1; --i) {
double sum = 0;
for (int j=i+1; j<=N; ++j) sum += a[i][j] * x[j];
x[i] = (a[i][N+1] - sum) / a[i][i];
}

k=j 導致主元列歸零,後續計算全錯。修正為 k=j+1 即正確。A、b 合併為增廣矩陣編程更便捷。區間 [x_i, x_{i+1}] 上構造三次多項式 S_i(x),滿足:函數值連續、一二階導數連續、邊界二階導數為 0(自然樣條)。導出三對角線性方程組求 M_i = S''(x_i),再由 M_i 計算插值點函數值與導數。
// 系統:λ_i M_{i-1} + 2 M_i + μ_i M_{i+1} = d_i
// 遞推:P_i = 2 - λ_i * L_{i-1}, L_i = μ_i / P_i, G_i = (d_i - λ_i * G_{i-1}) / P_i
// 回代:M_n = G_n; M_i = G_i - L_i * M_{i+1}
double h = 0.5; // 等距節點
double f[11] = {0, 0, log(2), log(3), ..., log(10)}; // 已知函數值
double lambda[11], mu[11], d[11], M[11];
// 設置 λ, μ, d(邊界條件 M_1=M_10=0 對應 λ_1=μ_10=0)
// 追趕法遞推
double P[11], L[11], G[11];
P[1] = 2; G[1] = d[1];
for (int i=2; i<=9; ++i) {
L[i] = lambda[i] / P[i-1];
P[i] = 2 - lambda[i] * L[i];
G[i] = d[i] - lambda[i] * G[i-1];
}
// 回代
M[10] = G[10] / P[10];
for (int i=9; i>=1; --i) M[i] = (G[i] - mu[i]*M[i+1]) / P[i];
// 計算 x=4.563 處函數值與導數(落在 [4,5] 區間)
double s = M[4]*pow(5-4.563,3)/6 + M[5]*pow(4.563-4,3)/6
+ (f[4]-M[4]/6)*(5-4.563) + (f[5]-M[5]/6)*(4.563-4);
double z = -M[4]/2*pow(5-4.563,2) + M[5]/2*pow(4.563-4,2)
- (f[4]-M[4]/6) + (f[5]-M[5]/6);

i-- 寫成 i++ 導致死循環;乘法漏寫 *(如 M[4]/2*(...))。assert 檢查分母非零、節點嚴格遞增等前置條件。三大經典算法完整實現,暴露出下標管理、循環邊界、數值穩定性等工程細節。數值計算「理論正確 ≠ 代碼正確」,嚴謹的邊界檢查、殘差驗證、單元測試不可或缺。