/********************************/ /* 補間法(3次スプライン関数) */ /* coded by Y.Suganuma */ /********************************/ #include <stdio.h> double spline(int, double *, double *, double, double *, double *, double *, double *, double *, double *); int main() { double *h, *b, *d, *g, *u, *r, *x, *y, sp, x1, y1; int n; // 設定 n = 5; h = new double [n]; b = new double [n]; d = new double [n]; g = new double [n]; u = new double [n]; r = new double [n+1]; x = new double [n+1]; y = new double [n+1]; x[0] = 0.0; x[1] = 1.0; x[2] = 2.0; x[3] = 3.0; x[4] = 4.0; x[5] = 5.0; y[0] = 0.0; y[1] = 1.0; y[2] = 4.0; y[3] = 9.0; y[4] = 16.0; y[5] = 25.0; // 実行と出力 x1 = 0.0; sp = 0.1; while (x1 <= 5.01) { y1 = spline(n, x, y, x1, h, b, d, g, u, r); printf("%f %f\n", x1, y1); x1 += sp; } delete [] h; delete [] b; delete [] d; delete [] g; delete [] u; delete [] r; delete [] x; delete [] y; return 0; } /**********************************/ /* 3次スプライン関数による補間 */ /* n : 区間の数 */ /* x, y : 点の座標 */ /* x1 : 補間値を求める値 */ /* h, b, d, g, u, r : 作業域 */ /* return : 補間値 */ /* coded by Y.Suganuma */ /**********************************/ double spline(int n, double *x, double *y, double x1, double *h, double *b, double *d, double *g, double *u, double *r) { int i = -1, i1, k; double y1, qi, si, xx; // 区間の決定 for (i1 = 1; i1 < n && i < 0; i1++) { if (x1 < x[i1]) i = i1 - 1; } if (i < 0) i = n - 1; // ステップ1 for (i1 = 0; i1 < n; i1++) h[i1] = x[i1+1] - x[i1]; for (i1 = 1; i1 < n; i1++) { b[i1] = 2.0 * (h[i1] + h[i1-1]); d[i1] = 3.0 * ((y[i1+1] - y[i1]) / h[i1] - (y[i1] - y[i1-1]) / h[i1-1]); } // ステップ2 g[1] = h[1] / b[1]; for (i1 = 2; i1 < n-1; i1++) g[i1] = h[i1] / (b[i1] - h[i1-1] * g[i1-1]); u[1] = d[1] / b[1]; for (i1 = 2; i1 < n; i1++) u[i1] = (d[i1] - h[i1-1] * u[i1-1]) / (b[i1] - h[i1-1] * g[i1-1]); // ステップ3 k = (i > 1) ? i : 1; r[0] = 0.0; r[n] = 0.0; r[n-1] = u[n-1]; for (i1 = n-2; i1 >= k; i1--) r[i1] = u[i1] - g[i1] * r[i1+1]; // ステップ4 xx = x1 - x[i]; qi = (y[i+1] - y[i]) / h[i] - h[i] * (r[i+1] + 2.0 * r[i]) / 3.0; si = (r[i+1] - r[i]) / (3.0 * h[i]); y1 = y[i] + xx * (qi + xx * (r[i] + si * xx)); return y1; }
/********************************/ /* 補間法(3次スプライン関数) */ /* coded by Y.Suganuma */ /********************************/ #include <stdio.h> /****************/ /* クラスの定義 */ /****************/ class Spline { double *h, *b, *d, *g, *u, *r, *q, *s, *x, *y; int n; public: /**************************/ /* コンストラクタ */ /* n1 : 区間の数 */ /* x1, y1 : 点の座標 */ /**************************/ Spline(int n1, double *x1, double *y1) { int i1; // 領域の確保 n = n1; h = new double [n]; b = new double [n]; d = new double [n]; g = new double [n]; u = new double [n]; q = new double [n]; s = new double [n]; r = new double [n+1]; x = new double [n+1]; y = new double [n+1]; for (i1 = 0; i1 <= n; i1++) { x[i1] = x1[i1]; y[i1] = y1[i1]; } // ステップ1 for (i1 = 0; i1 < n; i1++) h[i1] = x[i1+1] - x[i1]; for (i1 = 1; i1 < n; i1++) { b[i1] = 2.0 * (h[i1] + h[i1-1]); d[i1] = 3.0 * ((y[i1+1] - y[i1]) / h[i1] - (y[i1] - y[i1-1]) / h[i1-1]); } // ステップ2 g[1] = h[1] / b[1]; for (i1 = 2; i1 < n-1; i1++) g[i1] = h[i1] / (b[i1] - h[i1-1] * g[i1-1]); u[1] = d[1] / b[1]; for (i1 = 2; i1 < n; i1++) u[i1] = (d[i1] - h[i1-1] * u[i1-1]) / (b[i1] - h[i1-1] * g[i1-1]); // ステップ3 r[0] = 0.0; r[n] = 0.0; r[n-1] = u[n-1]; for (i1 = n-2; i1 >= 1; i1--) r[i1] = u[i1] - g[i1] * r[i1+1]; // ステップ4 for (i1 = 0; i1 < n; i1++) { q[i1] = (y[i1+1] - y[i1]) / h[i1] - h[i1] * (r[i1+1] + 2.0 * r[i1]) / 3.0; s[i1] = (r[i1+1] - r[i1]) / (3.0 * h[i1]); } } /****************/ /* デストラクタ */ /****************/ ~Spline() { delete [] h; delete [] b; delete [] d; delete [] g; delete [] u; delete [] q; delete [] s; delete [] r; delete [] x; delete [] y; } /******************************/ /* 補間値の計算 */ /* x1 : 補間値を求める値 */ /* return : 補間値 */ /******************************/ double value(double x1) { int i = -1, i1; double y1, xx; // 区間の決定 for (i1 = 1; i1 < n && i < 0; i1++) { if (x1 < x[i1]) i = i1 - 1; } if (i < 0) i = n - 1; // 計算 xx = x1 - x[i]; y1 = y[i] + xx * (q[i] + xx * (r[i] + s[i] * xx)); return y1; } }; /*************/ /* main 関数 */ /*************/ int main() { double *x, *y, sp, x1, y1; int n; // 設定 n = 5; x = new double [n+1]; y = new double [n+1]; x[0] = 0.0; x[1] = 1.0; x[2] = 2.0; x[3] = 3.0; x[4] = 4.0; x[5] = 5.0; y[0] = 0.0; y[1] = 1.0; y[2] = 4.0; y[3] = 9.0; y[4] = 16.0; y[5] = 25.0; Spline spline(n, x, y); // 実行と出力 x1 = 0.0; sp = 0.1; while (x1 <= 5.01) { y1 = spline.value(x1); printf("%f %f\n", x1, y1); x1 += sp; } delete [] x; delete [] y; return 0; }