Нахождение минимума функции одной переменной методами квадратичной и кубической параболы
Помогите с программой для курсовой. Если выбирать 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;
}