#include <iostream>
#include <math.h> // библиотека для математических вычислений, из нее используются функции pow и sqrt
using namespace std;
/*
* Для чего тут класс, и что такое класс. Вкратце, это структура, которая позволяет использовать вложенные методы и данные с разными областями видимости
* и инкапсуляцией методов и переменных, а также позволяет упрощать код с точки зрения читабельности и количеству строк.
*/
class GoldenRatio { // создаем класс Золотого сечения
private: // Приватная область, к переменным и функциям которой нельзя получить доступ извне
/*
* bool - булевый тип данных. Хранит только одно из значение: true - истина, либо ложь - false.
* findMax - название приватной переменной
*/
bool findMax;
/*
* Статичная константная функция, возвращающая значение пропорции золотого сечения фи
* Значение в формате плавающей точки с двойной точностью
*/
static const double thauma() {
/* Здесь sqrt - это функция, для вычисления квадратного корня из библиотеки <math.h>
* sqrt("число/выражение")
* sqrt(4) => 2, sqrt(25) => 5
*/
return (1.f + sqrt(5)) / 2.f;
//return 1.6180339887; // выражение, для вычисления пропорции золотого сечения ()
}
/* Статичная функция возвращающая значение с плавающей точкой двойной точности.
* Принимает как аргумент значение с плавающей точкой двойной точности (x).
* В ней хранится исходная функция, для которой будут находиться минимум и максимум.
*/
double static f(double x) {
/* pow - функция, для возведения в степень из библиотеки <math.h>
* pow("число/выражение", "степень")
* pow(5, 2) => 25, pow(2, 5) => 32
*/
return pow(x + 1.f, 2) + 5 * pow(x - 2.f, 3) + 2 * pow(x, 4); // (x + 1)^2 + 5 * (x - 2)^3 + 2 * x^4
}
public: // Публичная область, к переменным и функциям которой можно получить доступ вне класса
/*
* По сути конструктор представляет функцию, которая может принимать параметры и которая должна называться по имени класса.
* В данном случае конструктор принимает один параметр - findMax, и устанавливает его значение в приватной переменной this->findMax.
* В будущем, в классе будет обращение к этой переменой с проверкой, что мы ищем - максимум или минимум.
* explicit - это ключевое слово, которое необходимо указывать при объявлении конструктора с одним параметром (ну или если все другие параметры имеют default value)
*/
explicit GoldenRatio(bool findMax) { // Конструктор класса.
this->findMax = findMax;
}
double calculate(double a, double b, double e) {
/* x1 - переменная, хранящая результат расчетов левой точки деления на отрезки
* x2 - переменная, хранящая результат расчетов правой точки деления на отрезки
* delta - результат выражения (b - a) / thauma() в каждой итерации, переменная используется для
* хранения значения в памяти без повторных вычислений значений. можно везде заменить на (b - a) / thauma()
*/
double x1, x2, delta;
/*
* Цикл while будет выполняться, пока условие, указанное в круглых скобках является истиной.
* abs(b - a) > e - условие проверки достижения указанной точности
* Если точность достигнута - цикл будет прерван и функция вернет вычисленное значение (a + b) / 2;
* Если точность не достигнута, то будут происходить расчет переменных a и b, путем итеративного разбивания отрезков
*/
while (b - a > e) {
delta = (b - a) / thauma(); // создал временную переменную, чтобы дважды не вычислять это значение
/*
* Рассчет координат точек деления, при каждой итерации цикла, исходный отрезок делится на более меньшие отрезки
*/
x1 = b - delta;
x2 = a + delta;
if(this->findMax) { // Проверка ищем ли мы максимум, или минимум (зависит от ввода пользователя)
if (f(x1) <= f(x2)) { // если функция от x1 больше или равна функции от х2, то
a = x1; // сдвиг значения для следующей итерации
} else { // в противном случае
b = x2; // сдвиг значения для следующей итерации
}
} else { // Тут типо ищем минимум
if (f(x1) >= f(x2)) { // если функция от x1 меньше или равна функции от х2, то
a = x1; // сдвиг значения для следующей итерации
} else { // в противном случае
b = x2; // сдвиг значения для следующей итерации
}
}
cout << "lambda = " << a + (1.f - 0.618) * (b - a) << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
return (a + b) / 2; // возврат значения
}
};
int main() {
/*
* Исходные данные:
* f(x) = (x + 1)^2 + 5 * (x - 2)^3 + 2 * x^4
* Значения, которые я сверял через онлайн-калькулятор https://math.semestr.ru/optim/golden.php
* a = -8, b = 0, e = 0.0001;
* Поиск минимума:
* Результат калькулятора: -4.102617955
* Результат программы: -4.10260066
*/
double a = -8.f, b = 0, e = 0.0001;
//double a, b, e;
int value;
//cout << "Enter a:";
//cin >> a;
//cout << "Enter b:";
//cin >> b;
//cout << "Enter epsilon:";
//cin >> e;
//cout << "If u want find maximum enter 1 or enter any value for find minimum:";
//cin >> value;
GoldenRatio *object = new GoldenRatio(false);
std::cout.precision(9);
std::cout.setf(std::ios::fixed);
cout << endl << endl << object->calculate(a, b, e);
}