lab8

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdio.h> // printf, scanf
#include <conio.h> // getch
#include <math.h> // Математические функции (sin cos atan exp pow и т.д.) и константа Пи - M_PI
//---------------------------------------------------------------------------
struct result { // структура для возврата результата вычислений разными методами
int iters;
double root;
};
double f1(double x) { // первая функция (11 вариант)
return cos((0.7854-x*sqrt(4.0-x*x))/(2.0-x) + 2.0/7.0) - x;
}
double f2(double x) { // вторая функция (11+3 = 14 вариант)
return 2.0/3.0*acos(sqrt(x/2.0)) + 0.577*log(x+1) + pow(0.01, 1.0/3.0) - x;
}
void printHeader(int num) { // вывод заголовка таблицы с результатами
printf(" Функция %d Метод деления пополам Метод секущих\n", num);
printf("|Погрешность | Корень |Итераций| Корень |Итераций|\n");
//printf("%10s |");
}
result bisect(double a, double b, int n, double (*f)(double)) { // функция для нахождения примерного корня и числа итераций методом бисекции
result res; // структура для возврата корня и числа итераций
res.iters = 0;
double epsilon = pow(0.1, n); // получаем необходимую точность как 10 в степени -n
while ((b - a) > epsilon) {
double x = a + (b - a)/2.0; // находим середину отрезка
if (f(a)*f(x) > 0) { // если корень лежит справа от середины
a = x; // перемещаем а в середину
} else { // иначе
b = x; // перемещаем b в середину
}
res.iters += 1; // увеличиваем число итераций
}
res.root = a + (b-a)/2; // присваиваем значение корня в поле структуры результата
return res;
}
result secant(double a, double b, int n, double (*f)(double)) { // функция для нахождения примерного корня и числа итераций методом секущих
result res;
double epsilon = pow(0.1, n); // точность
double x1 = a; // устанавливаем начальные значения
double x2 = b;
double x3 = x1 - f(x1)*(x2 - x1)/(f(x2)-f(x1)); // находим точку пересечения
res.iters = 1; // по сути одна итерация прошла
while (fabs(x3 - x2) > epsilon) {
x1 = x2; // сдвигаем границы отрезка
x2 = x3;
x3 = x1 - f(x1)*(x2 - x1)/(f(x2)-f(x1)); // находим точку пересечения
res.iters += 1;
}
res.root = x3; // возвращаем х3 как приблизительный корень
return res;
}
void error_msg(const char* reason) { // Вывод сообщения об ошибке при аномалии с причиной
printf("Ошибка! %s\n", reason);
printf("Press any key to exit\n");
getch();
}
int sign(double x) {
return x > 0 ? 1 : (x < 0 ? -1 : 0);
}
int main()
{
int n; // целое
float a, b; // вещ.число с плавающей точкой двойной точности
printf("Введите координаты точек A и B отрезка AB (0<A<B<2)\n");
scanf("%f %f", &a, &b); // ввод a и b
// проверки на аномалии, какие именно очевидно из сообщений об ошибке
if (a < 0) {
error_msg("Левый конец должен быть больше 0!");
return 1;
}
if (b > 2) {
error_msg("Правый конец должен быть меньше 2!");
return 1;
}
if (a >= b) {
error_msg("Правый конец должен быть больше левого!");
return 1;
}
printf("Введите N от 1 до 10 (кол-во шагов для разных точностей)\n");
scanf("%d", &n);
if (n < 1 || n > 10) { // проверка на аномалию для n
error_msg("N должно быть 1<=N<=10!");
return 1;
}
if (f1(a)*f1(b) > 0) {
printf("Корня на отрезке AB для первой функции нет"); // если нет корня первой функции на отрезке
} else {
printHeader(1);
for (int i = 1; i <= n; i++) {
result bm = bisect(a, b, i, f1);
result sm = secant(a, b, i, f1);
printf("|%12.10f|%13.10f|%8d|%13.10f|%8d|\n", pow(0.1, i), bm.root, bm.iters, sm.root, sm.iters);
}
}
printf("\n");
if (f2(a)*f2(b) > 0) {
printf("Корня на отрезке AB для второй функции нет"); // если нет корня второй функции на отрезке
} else {
printHeader(2);
for (int i = 1; i <= n; i++) {
result bm = bisect(a, b, i, f2); // получаем корень и число итераций методом бисекции
result sm = secant(a, b, i, f2); // получаем корень и число итераций методом секущих
printf("|%12.10f|%13.10f|%8d|%13.10f|%8d|\n", pow(0.1, i), bm.root, bm.iters, sm.root, sm.iters); // выводим строку в таблице
}
}
printf("\nPress any key to exit\n");
getch(); // задержка консольного экрана до нажатия любой клавиши
return 0; //выход из main()
}