/*********************************************/ /* 黄金分割法によるy=x^4+3x^3+2x^2+1の最小値 */ /* coded by Y.Suganuma */ /*********************************************/ #include <stdio.h> double snx(double); double gold(double, double, double, double *, int *, int, double (*)(double)); int main() { double a, b, eps, val, x; int ind, max; a = -2.0; b = -1.0; eps = 1.0e-10; max = 100; x = gold(a, b, eps, &val, &ind, max, snx); printf("x %f val %f ind %d\n", x, val, ind); return 0; } /****************/ /* 関数値の計算 */ /****************/ double snx(double x) { double f; f = x * x * x * x + 3.0 * x * x * x + 2.0 * x * x + 1.0; return f; } /******************************************/ /* 黄金分割法(関数の最小値) */ /* a,b : 初期区間 a < b */ /* eps : 許容誤差 */ /* val : 間数値 */ /* ind : 計算状況 */ /* >= 0 : 正常終了(収束回数) */ /* = -1 : 収束せず */ /* max : 最大試行回数 */ /* fun : 関数値を計算する関数の名前 */ /* return : 結果 */ /******************************************/ #include <math.h> double gold(double a, double b, double eps, double *val, int *ind, int max, double (*fun)(double)) { double f1, f2, fa, fb, tau, x = 0.0, x1, x2; int count; tau = (sqrt(5.0) - 1.0) / 2.0; count = 0; *ind = -1; x1 = b - tau * (b - a); x2 = a + tau * (b - a); f1 = fun(x1); f2 = fun(x2); while (count < max && *ind < 0) { count += 1; if (f2 > f1) { if (fabs(b-a) < eps && fabs(b-a) < eps*fabs(b)) { *ind = 0; x = x1; *val = f1; } else { b = x2; x2 = x1; x1 = a + (1.0 - tau) * (b - a); f2 = f1; f1 = fun(x1); } } else { if (fabs(b-a) < eps && fabs(b-a) < eps*fabs(b)) { *ind = 0; x = x2; *val = f2; f1 = f2; } else { a = x1; x1 = x2; x2 = b - (1.0 - tau) * (b - a); f1 = f2; f2 = fun(x2); } } } if (*ind == 0) { *ind = count; fa = fun(a); fb = fun(b); if (fb < fa) { a = b; fa = fb; } if (fa < f1) { x = a; *val = fa; } } return x; }