
Добавил:
webxxcom
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:ЛБ5 / main
.cpp#include <iostream>
#include <vector>
constexpr double exact_answer = -25.65;
constexpr double left = -2;
constexpr double right = 1;
constexpr double a = -4;
constexpr double b = -1;
constexpr double c = 1;
constexpr double d = -4;
constexpr double e = -4;
constexpr int n = 20;
constexpr double h = (right - left) / n;
static double fx(double x)
{
return a * pow(x, 4) + b * pow(x, 3) + c * pow(x, 2) + d * x + e;
}
static double first_derivative(double x)
{
return 4 * a * pow(x, 3) + 3 * b * pow(x, 2) + 2 * c * x + d;
}
static double second_derivative(double x)
{
return 12 * a * pow(x, 2) + 6 * b * x + 2 * c;
}
static double third_derivative(double x)
{
return 24 * a * x + 6 * b;
}
static double fourth_derivative(double x)
{
return 24 * a;
}
static bool has_root_at_the_interval(const double left, const double right)
{
double left_value = first_derivative(left);
double right_value = first_derivative(right);
return left_value * right_value < 0;
}
static std::vector<double> find_the_critical_points()
{
std::vector<double> crit_points;
double temp_a = a * 12.;
double temp_b = b * 6.;
double D = temp_b * temp_b - 4. * temp_a * c * 2;
if (D > 0)
{
double x1 = (-temp_b + sqrt(D)) / (2. * temp_a);
double x2 = (-temp_b - sqrt(D)) / (2. * temp_a);
if (x1 >= left && x1 <= right && x2 >= left && x2 <= right)
{
if (x1 > x2)
std::swap(x1, x2);
crit_points.insert(crit_points.end(), { x1,x2 });
}
else if (x1 >= left && x1 <= right)
crit_points.emplace_back(x1);
else if(x2 >= left && x2 <= right)
crit_points.emplace_back(x2);
}
else if (D == 0)
crit_points.emplace_back(-temp_b / (2. * temp_a));
else
{
std::cerr << "\nThe given function has no critical points.\n" <<
"The separation of the roots CAN NOT be performed.\n";
exit(EXIT_FAILURE);
}
return crit_points;
}
static std::vector<double> find_intervals()
{
const std::vector<double> crit_points = find_the_critical_points();
std::vector<double> points;
double dx = 0.1;
double right_limit;
double left_limit;
const int MAX_ITERATIONS = 3000;
for (size_t i = 0; i < crit_points.size(); i++)
{
right_limit = crit_points[i] - dx;
left_limit = right_limit - dx;
int j = 0;
while (j <= MAX_ITERATIONS)
{
if (i > 0)
{
dx = std::abs(left_limit - crit_points[i - 1]) / 2;
if (std::abs(left_limit - crit_points[i - 1]) < 0.01)
break;
}
left_limit -= dx;
if (has_root_at_the_interval(left_limit, right_limit))
{
points.insert(points.end(), { left_limit, right_limit });
break;
}
++j;
}
}
left_limit = crit_points.back() + dx;
right_limit = left_limit + dx;
int j = 0;
while (j <= MAX_ITERATIONS)
{
++right_limit;
if (fx(left_limit) * fx(right_limit) < 0)
{
points.insert(points.end(), { left_limit, right_limit });
break;
}
++j;
}
return points;
}
static std::vector<double> combined_method()
{
std::vector<double> roots;
std::vector<double> intervals = find_intervals();
int k = 0;
for (size_t i = 0; i < intervals.size(); i += 2)
{
double a_k = (intervals[i] + intervals[i + 1]) / 2;
double b_k;
if (second_derivative(a_k) * third_derivative(a_k) < 0)
{
a_k = intervals[i];
b_k = intervals[i + 1];
}
else
{
b_k = intervals[i];
a_k = intervals[i + 1];
}
while (std::abs(a_k - b_k) > 2 * 0.001)
{
b_k = b_k - (second_derivative(b_k) * (a_k - b_k)) / (second_derivative(a_k) - second_derivative(b_k));
a_k = a_k - (second_derivative(a_k) / third_derivative(a_k));
++k;
}
roots.emplace_back((a_k + b_k) / 2);
}
return roots;
}
static double LeftRectangle()
{
double sum = 0.;
for (int i = 0; i < n; ++i)
sum += fx(left + i * h);
return h * sum;
}
static double RightRectangle()
{
double sum = 0.;
for (int i = 1; i <= n; ++i)
sum += fx(left + i * h);
return h * sum;
}
static double Trapezoidal()
{
double sum = (fx(left) + fx(right)) / 2.;
for (int i = 1; i < n; ++i)
sum += fx(left + i * h);
return h * sum;
}
static double Simpsons()
{
double sum = fx(left) + fx(right);
for (int i = 1; i < n; ++i)
{
if (i % 2 == 0)
sum += 2 * fx(left + i * h);
else
sum += 4 * fx(left + i * h);
}
return h * sum / 3.;
}
static double max_value_of_m1()
{
std::vector<double> crit_points = combined_method();
double value = std::max(std::abs(first_derivative(left)), std::abs(first_derivative(right)));
for (double number : crit_points)
value = std::max(value, std::abs(number));
return value;
}
static double LeftAndRightError()
{
double m1 = max_value_of_m1();
return h * (right - left) * m1 / 2.;
}
static double max_value_of_m2()
{
double crit_point = 6 * -b / (2. * 12 * a);
return std::max({ std::abs(second_derivative(left)), std::abs(second_derivative(right)), std::abs(crit_point) });
}
static double TrapezoidalError()
{
double m2 = max_value_of_m2();
return pow(h, 2) / 12 * (right - left) * m2;
}
static double SimpsonError()
{
double m3 = std::abs(fourth_derivative( 24 * a));
return pow(h, 4) * (right - left) * m3 / 180;
}
int main()
{
std::cout << "Left Rectangle.\n\tAnswer: " << LeftRectangle() << '\n' << "\tMax error: " << LeftAndRightError() << '\n' << "\tAbsolute Error: " << abs(exact_answer - LeftRectangle()) << '\n';
std::cout << "\nRight Rectangle.\n\tAnswer: " << RightRectangle() << '\n' << "\tMax error: " << LeftAndRightError() << '\n' << "\tAbsolute Error: " << abs(exact_answer - RightRectangle()) << '\n';
std::cout << "\nTrapezoidal.\n\tAnswer: " << Trapezoidal() << '\n' << "\tMax error: " << TrapezoidalError() << '\n' << "\tAbsolute Error: " << abs(exact_answer - Trapezoidal()) << '\n';
std::cout << "\nSimpson's.\n\tanswer: " << Simpsons() << '\n' << "\tMax error: " << SimpsonError() << '\n' << "\tAbsolute Error: " << abs(exact_answer - Simpsons()) << '\n';
return 0;
}