#include <iostream> // библиотека для работы с потоками вывода/ввода данных, cin, cout, ...
#include <math.h> // библиотека для математических вычислений, из нее используются функции pow и sqrt
using namespace std;
/*
* Для чего тут класс, и что такое класс. Вкратце, это структура, которая позволяет использовать вложенные методы и данные с разными областями видимости
* и инкапсуляцией методов и переменных, а также позволяет упрощать код с точки зрения читабельности и количеству строк.
*/
class GoldenRatio { // создаем класс Золотого сечения
private: // Приватная область, к переменным и функциям которой нельзя получить доступ извне
/*
* bool - булевый тип данных. Хранит только одно из значение: true - истина, либо ложь - false.
* findMax - название приватной переменной
*/
bool findMax;
/*
* Статичная константная функция, возвращающая значение пропорции золотого сечения фи
* Значение в формате плавающей точки с двойной точностью
*/
static const double phi() {
/* Здесь sqrt - это функция, для вычисления квадратного корня из библиотеки <math.h>
* sqrt("число/выражение")
* sqrt(4) => 2, sqrt(25) => 5
*/
return (1 + sqrt(5)) / 2;
//return 1.6180339887; // выражение, для вычисления пропорции золотого сечения ()
}
/* Статичная функция возвращающая значение с плавающей точкой двойной точности.
* Принимает как аргумент значение с плавающей точкой двойной точности (x).
* В ней хранится исходная функция, для которой будут находиться минимум и максимум.
*/
public: // Публичная область, к переменным и функциям которой можно получить доступ вне класса
/*
* По сути конструктор представляет функцию, которая может принимать параметры и которая должна называться по имени класса.
* В данном случае конструктор принимает один параметр - findMax, и устанавливает его значение в приватной переменной this->findMax.
* В будущем, в классе будет обращение к этой переменой с проверкой, что мы ищем - максимум или минимум.
* explicit - это ключевое слово, которое необходимо указывать при объявлении конструктора с одним параметром (ну или если все другие параметры имеют default value)
*/
explicit GoldenRatio(bool findMax) { // Конструктор класса.
this->findMax = findMax;
}
double f(double x) {
/* pow - функция, для возведения в степень из библиотеки <math.h>
* pow("число/выражение", "степень")
* pow(5, 2) => 25, pow(2, 5) => 32
*/
return pow(x, 2) + 5 * pow(x, 3); // x^2 + 5 * x^3
}
double calculate(double a, double b, double e) {
/* x1 - переменная, хранящая результат расчетов левой точки деления на отрезки
* x2 - переменная, хранящая результат расчетов правой точки деления на отрезки
* delta - результат выражения (b - a) / phi() в каждой итерации, переменная используется для
* хранения значения в памяти без повторных вычислений значений. можно везде заменить на (b - a) / phi()
*/
double x1, x2, delta;
/*
* Цикл while будет выполняться, пока условие, указанное в круглых скобках является истиной.
* abs(b - a) > e - условие проверки достижения указанной точности
* Если точность достигнута - цикл будет прерван и функция вернет вычисленное значение (a + b) / 2;
* Если точность не достигнута, то будут происходить расчет переменных a и b, путем итеративного разбивания отрезков
*/
while (b - a > e) {
delta = (b - a) / phi(); // создал временную переменную, чтобы дважды не вычислять это значение
/*
* Рассчет координат точек деления, при каждой итерации цикла, исходный отрезок делится на более меньшие отрезки
*/
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; // сдвиг значения для следующей итерации
}
}
}
return (a + b) / 2; // возврат значения x
}
};
int main() {
/*
* Исходные данные:
* f(x) = x^2 + 5 * x^3
* Значения, которые я сверял через онлайн-калькулятор https://math.semestr.ru/optim/golden.php
* double a = -8.f, b = 0, e = 0.0001;
* Поиск минимума:
* Результат калькулятора: x = -7.999998675; F(x) = -2495.9987
* Результат программы: x = -7.99996; F(x) = -2495.96
* Поиск максимума:
* Результат калькулятора: x = -0.13333222; F(x) = -0.00593
* Результат программы: x = -0.133349; F(x) = 0.00592593 // ??
*/
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;
/*
* Тут создается объект object класса GoldenRatio, и в конструктор передается value == 1
* value == 1 - это условие, оно вернет true - если value равно 1, в противном случае false
*/
GoldenRatio *object = new GoldenRatio(value == 1);
/*
* Тут вызывается метод calculate объекта object
* В него передаются введенные пользователем данные в качестве аргументов
*/
double x = object->calculate(a, b, e);
cout << endl << "x = " << x << "; F(x) = " << object->f(x); // вывод на экран значения x, и значения функции от x.
}