Нахождение минимума функции одной переменной методами квадратичной и кубической параболы

Помогите с программой для курсовой. Если выбирать log, sin, cos,sqrt то виснет прога. С x^2 и x^3 вроде работает (Но не факт что верно).

#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

//Прототипы
double f1(double);
double f2(double);
double f3(double);
double f4(double);
double f5(double);
double f6(double);
double f(double);
double quadraticParabola(double, double, double, double (*)(double));
double cubicParabola(double, double, double, double (*)(double));

int main() {
    setlocale(LC_ALL, "RU");

    int k;
    double a, b, epsilon;

    double (*f)(double);

    cout << "Выберете функцию(1 - (x)^1/2, 2 - x^2, 3 - x^3, 4 - ln(x), 5 - sin(x), 6 - cos(x): ): " << endl;
    cin >> k;

    switch (k) {
    case 1: {
        f = f1;
    } break;
    case 2: {
        f = f2;
    } break;
    case 3: {
        f = f3;
    } break;
    case 4: {
        f = f4;
    } break;
    case 5: {
        f = f5;
    } break;
    case 6: {
        f = f6;
    } break;
    default: {cout << "Функция не выбрана" << endl;
        return 1;
    }
    }

    cout << "Введите левую границу интервала: " << endl;
    cin >> a;
    cout << "Введите правую границу интервала: " << endl;
    cin >> b;
    cout << "Введите заданную точность (в виде 1e-n, где n любое число): " << endl;
    cin >> epsilon;

    double minQuadratic = quadraticParabola(a, b, epsilon, *f);
    double minCubic = cubicParabola(a, b, epsilon, *f);

    cout << "Минимум (метод квадратичной параболы): " << minQuadratic << endl;
    cout << "Минимум (метод кубической параболы): " << minCubic << endl;

    return 0;
}

double f1(double x) {
    return sqrt(x);
}
double f2(double x) {
    return pow(x, 2);
}
double f3(double x) {
    return pow(x, 3);
}
double f4(double x) {
    return log(x);
}
double f5(double x) {
    return sin(x);
}
double f6(double x) {
    return cos(x);
}
//Метод квадратичной параболы
double quadraticParabola(double a, double b, double epsilon, double (*f)(double)) {
    double x1, x2, x3;
    double f1, f2, f3;

    do {
        x1 = (a + b) / 2;
        x2 = (a + x1) / 2;
        x3 = (x1 + b) / 2;

        f1 = f(x1);
        f2 = f(x2);
        f3 = f(x3);

        if (f2 < f1 && f2 < f3) {
            b = x3;
        }
        else {
            a = x2;
        }
    } while (abs(b - a) > epsilon);

    return (a + b) / 2;
}

//Метод кубической параболы
double cubicParabola(double a, double b, double epsilon, double (*f)(double)) {
    double x1, x2, x3, x4;
    double f1, f2, f3, f4;

    do {
        x1 = a + (b - a) / 4;
        x2 = a + (b - a) / 2;
        x3 = b - (b - a) / 4;

        f1 = f(x1);
        f2 = f(x2);
        f3 = f(x3);

        double A = ((f2 - f3) / (x2 - x3) - (f1 - f2) / (x1 - x2)) / (x1 - x3);
        double B = (f2 - f1) / (x1 - x2) - A * (x1 + x2);
        x4 = -B / (2 * A);

        f4 = f(x4);

        if (f4 < f2) {
            if (x4 < x2) {
                b = x2;
            }
            else {
                a = x2;
            }
        }
        else {
            if (x4 < x2) {
                a = x4;
            }
            else {
                b = x4;
            }
        }
    } while (abs(b - a) > epsilon);

    return (a + b) / 2;
}

Ответы (1 шт):

Автор решения: Deloperr

я уже смог исправить сам, поэтому вот, если кому надо

#include <iostream>
#include <cmath>

using namespace std;

//Прототипы
double f1(double);
double f2(double);

double d1(double);
double d2(double);

double quadraticParabola(double, double, double, double (*)(double));
double cubicParabola(double, double, double, double (*)(double), double (*)(double));

int main() {
    setlocale(LC_ALL, "RU");

    int k, g, v = 1, m = 1; 
    double a, b, h, x0;
    double epsilon = pow(10, -6);
    double (*f)(double);
    double (*d)(double);
    d = d1; f = f1;
    while (v == 1)
    {
        m = 1;
        cout << "Выберете функцию: " << endl;
        cin >> k;

        switch (k) {
        case 1: {
            f = f1;
            d = d1;
            v = 2;

            a = -4;
            b = 9;
            x0 = 2;
        } break;
        case 2: {
            f = f2;
            d = d2;
            v = 2;

            a = -6;
            b = 3;
            x0 = -5;
        } break;
        default: { cout << "Неверный номер" << endl; //выбор, вернуться или нет(1 да, остальное закрывается прога
            m = 2;
            cout << "Продолжить? (1- Да) ";
            cin >> v;
        }
        }
    }

    while (v == 1) { //возврат
        system("pause"); return 1;
    }
    cout << endl;
    if (m == 1) {
        cout << "Выбор a, b, x0 (1 - ввод, остальное по умолчанию)" << endl;
        cin >> g;
        switch (g) {
        case 1:
            cout << "Введите левую границу интервала: " << endl;
            cin >> a;
            cout << "Введите правую границу интервала: " << endl;
            cin >> b;
            cout << "Введите некоторую точку: " << endl;
            cin >> x0; break;
        default: cout << "Значения по умолчанию:" << endl;
            cout << "a = " << a << endl;
            cout << "b = " << b << endl;
            cout << "x0 = " << x0 << endl;
        }
        h = (a + b) / 2;
        double minXQuadratic = quadraticParabola(h, x0, epsilon, *f);
        double minXCubic = cubicParabola(h, x0, epsilon, *f, *d);
        double minQuadratic = f(minXQuadratic);
        double minCubic = f(minXCubic);
        cout << "Точка минимума (метод квадратичной параболы): " << minXQuadratic << endl;
        cout << "Минимум (метод квадратичной параболы): " << minQuadratic << endl;
        cout << "Точка минимума (метод кубической параболы): " << minXCubic << endl;
        cout << "Минимум (метод кубической параболы): " << minCubic << endl;

    }
    return 0;
}

double f1(double x) {
    return x * x - 4 * x * sin(x) + cos(x); //a = -4, b = 9, x0 = 2
}
double f2(double x) {
    return x*sin(x)-10*sin(x)*sin(x); //a = -6, b = 3, x0 = -5
}

double d1(double x) {
    return 2*x - 5 * sin(x) - 4 * x * cos(x);
}
double d2(double x) {
    return sin(x)+x*cos(x)-10*sin(2*x);
}
//Метод квадратичной параболы
double quadraticParabola(double h, double x0, double epsilon, double (*f)(double)) {
    double x1, x2, x3;
    double f1, f2, f3;
    double z1, z2;
    double p, q, zm, r;

        x1 = x0 - h;
        x2 = x0;
        x3 = x0 + h;

        f1 = f(x1);
        f2 = f(x2);
        f3 = f(x3);
        if (f1 - 2 * f2 + f3 > 0) {
            do {
            z1 = x1 - x3;
            z2 = x2 - x3;
            r = f3;
            p = ((f1 - f3) * z2 - (f2 - f3) * z1) / (z1 * z2 * (z1 - z2));
            q = ((f1 - f3) * (z2 * z2) - (f2 - f3) * (z1 * z1)) / (z1 * z2 * (z2 - z1));
            zm = -q / (2 * p);
            x1 = x2;
            x2 = x3;
            f1 = f2;
            f2 = f3;
            x3 = x3 + zm;
            f3 = f(x3);
            } while (abs(zm) > epsilon);
        }
        else {
            cout << "Начальное приближенме выбрано неправильно" << endl;
            return 0;
        }
    return x3 + zm;
}

//Метод кубической параболы
double cubicParabola(double h, double x0, double epsilon, double (*f)(double), double (*d)(double)) {
    double x1, x2;
    double f1, f2;
    double d1, d2;
    double z1;
    double p, q, r, zm;
    x1 = x0;
    d1 = d(x1);
    if (d1 > 0)
    {
        h = -h;
    }
    x2 = x1 + h;
    d2 = d(x2);
    if ((d2 - d1) / h < 0) {
            f1 = f(x1);
            f2 = f(x2);
          do {
            z1 = x1 - x2;
            p = (d1 - d2 - 2 * (f1 - f2 - d2 * z1) / z1) / (z1 * z1);
            q = (d2 - d1 + 3 * (f1 - f2 - d2 * z1) / z1) / z1;
            r = d2;
            zm = (-q + sqrt((q * q) - (3 * p * r))) / (3 * p);
            x1 = x2;
            f1 = f2;
            d1 = d2;
            x2 = x2 + zm;
            f2 = f(x2);
            d2 = d(x2);
        } while (abs(zm) > epsilon);
    }
    else {
        cout << "Начальное приближенме выбрано неправильно" << endl;
        return 0;
    }
    return x2 + zm;
}
→ Ссылка