From 34339041112c2d4177068b9d64b95f6b89fc8d92 Mon Sep 17 00:00:00 2001 From: ada-dmitry Date: Fri, 1 Dec 2023 14:30:50 +0300 Subject: [PATCH] added 1.3 --- Project_1.2/declare.h | 4 +- Project_1.2/functions.c | 40 ++-- Project_1.2/main.c | 15 +- Project_1.2/out/function_zeros_calculator | Bin 16896 -> 16896 bytes Project_1.3/Makefile | 24 +++ Project_1.3/README | 32 ++++ Project_1.3/declare.h | 13 ++ Project_1.3/functions.c | 214 ++++++++++++++++++++++ Project_1.3/main.c | 94 ++++++++++ Project_1.3/out/function_zeros_calculator | Bin 0 -> 21168 bytes 10 files changed, 414 insertions(+), 22 deletions(-) create mode 100644 Project_1.3/Makefile create mode 100644 Project_1.3/README create mode 100644 Project_1.3/declare.h create mode 100644 Project_1.3/functions.c create mode 100644 Project_1.3/main.c create mode 100755 Project_1.3/out/function_zeros_calculator diff --git a/Project_1.2/declare.h b/Project_1.2/declare.h index 2004142..8ae0808 100644 --- a/Project_1.2/declare.h +++ b/Project_1.2/declare.h @@ -1,6 +1,8 @@ extern double a, b, eps, x, *pa, *pb, *px; +// Декларирование глобальных переменных, +// как внешних для последующего использования их во всей программе. double f(double x); void ctrlc_handler(int signum); void choose_path(); -void fork_method(); \ No newline at end of file +void fork_method(); diff --git a/Project_1.2/functions.c b/Project_1.2/functions.c index dab0c56..b18c0e3 100644 --- a/Project_1.2/functions.c +++ b/Project_1.2/functions.c @@ -7,34 +7,38 @@ #include "declare.h" -double f(double x) +double f(double x) // Функция, заданная пользователем, для которой происходит поиск корней. { return x - 16; } -void fork_method() +void fork_method() // Функция поиска корней, использующая метод вилки. { do { *px = (*pa + *pb) / 2; // метод деления отрезка пополам + // Печать границ для отладки и для отслеживания хода вычислений printf("%lf %lf\n", *pa, *pb); + + // Проверка, какой из отрезков [a, x] или [x, b] подходит под условие существования корня, + // т.е. различие знаков на границе. if (f(*pa) * f(x) <= 0) *pb = x; else if (f(*pb) * f(x) <= 0) *pa = x; - sleep(1); + sleep(1); // Принудительное ожидание программой, для возможности прерывания пользователем. } while (fabs(*pb - *pa) > eps && f(x) != 0); return; } -void choose_path() +void choose_path() // Функция выбора действия после вызова сигнала. { char choice, *ch = &choice; - struct termios term; + struct termios term; // Задание структуры, определяющей терминал Linux. // Получение текущих настроек терминала tcgetattr(0, &term); @@ -46,23 +50,31 @@ void choose_path() tcsetattr(0, TCSANOW, &term); printf("\nПродолжить поиск корня?\n"); + printf("\nC - продолжить, A - закончить работу программы, \ +R - начать поиск на другом отрезке: \n"); + + // Очистка стандартного потока ввода от "лишних" __fpurge(stdin); + do { - printf("\nC - продолжить, A - закончить работу программы, R - начать поиск на другом отрезке: \n"); - *ch = getchar(); + *ch = getchar(); // Запись буквы, введенной пользователем в переменную choice. + switch (*ch) { - case 'C': + case 'C': // Выбор вида "Продолжить вычисление". case 'c': - return; - case 'A': + return; // Выход из функции без каких-либо изменений. + + case 'A': // Выбор вида "Завершить вычисление". case 'a': printf("\nКорень уравнения: %lf\n", *px); printf("Работа программы завершена.\n"); - exit(0); - case 'R': + exit(0); // Принудительное завершение программы с выводом текущего приближения корня. + + case 'R': // Выбор вида "Продолжить вычисления с новым отрезком". case 'r': + // Включение символа ECHO term.c_lflag |= ECHO; @@ -94,7 +106,7 @@ void choose_path() return; default: - printf("Ошибка ввода, повторная попытка..."); + printf("Ошибка ввода, повторная попытка...\n"); } } while (*ch != 'A' || *ch != 'R' || *ch != 'C' || *ch != 'a' || *ch != 'r' || *ch != 'c'); @@ -105,7 +117,7 @@ void choose_path() tcsetattr(0, TCSANOW, &term); } -void ctrlc_handler(int signum) +void ctrlc_handler(int signum) // Функция, заменяющая стандартный алгоритм для сигнала SIGINT. { printf("\nТекущее приближение: %lf\n", *px); choose_path(); diff --git a/Project_1.2/main.c b/Project_1.2/main.c index 4c8e845..438878b 100644 --- a/Project_1.2/main.c +++ b/Project_1.2/main.c @@ -15,20 +15,21 @@ int main() pb = &b; px = &x; - struct sigaction sig; + struct sigaction sig; // Инициализация структуры, отвечающей за обработку сигнала. + // Замена стандартного алгоритма на необходимый для вызова меню действий. sig.sa_handler = ctrlc_handler; - sig.sa_flags = 0; - sigemptyset(&sig.sa_mask); + sig.sa_flags = 0; // Очистка флагов "на всякий случай". + sigemptyset(&sig.sa_mask); // Очистка маски "на всякий случай". - printf("Введите интервал [a, b] и точность eps: "); - scanf("%lf %lf %lf", pa, pb, &eps); - - if (sigaction(SIGINT, &sig, NULL) == -1) + if (sigaction(SIGINT, &sig, NULL) == -1) // Обработчик ошибок и инициализация сигнала SIGINT. { perror("sigaction"); return 1; } + printf("Введите интервал [a, b] и точность eps: "); + scanf("%lf %lf %lf", pa, pb, &eps); + if (*pa > *pb) // Если пользователь перепутал границы { printf("Границы указаны неверно, запуск задачи с исправленным условием\n"); diff --git a/Project_1.2/out/function_zeros_calculator b/Project_1.2/out/function_zeros_calculator index bd65769928e605e31e873fdecb53d1342c8ce5cd..02089a8e051170ffa8ee78b7d7d3a286d69819d0 100755 GIT binary patch delta 1064 zcmYjQYe*DP6rMXe>iU}9+|gYTAE9fqnQjS6nvc|4BM>4t?i_>oj8Mt ziVI=n#es&TsfGg-HY}EqG@?mQQs_SfJG-g9v>4<*cD*5cHvC3Ye?sAU-JVb>cKX?P z@(hFsLyNVNQaUC@n(cFwETU`ah|)F>y{9*Kaj!!q$Gq$8A4*3FdN)j{LC2ut7?mPj z?=Zsb5GGEd%fY>ppeyW&1ok=9zVX#Emf|dQ&^7ZRNEAlYv2$CUEC+Q zrA^U(3}cuY{@U~oui+dVeTH zjlsdKBul{5nEA#jZ2G+tqEsFA$Z6J~PnSv7U`3Zmj$mI`su}hs9^aD%TnJR?4WTi3 zlp6ljw1wNyfJ1*-XjaJum1K2_wj11fT}!z)0fWYkM>qj2-R`xye@WdI5AY*QP62P7 zlz)vvukco<4=v=aFMMbfZ|(7+cX(@?53S~{7Nm~i@wNr9MMsidcpe>jp%beu&g}BB z2W4jay1C7*wl^Q*T-xz6`pkt>n)4n7W0ZT-ivR8L;tV4mLA6@Qg5Vof|@VS)`3YmdKW3%0&fYQqyR|De=~xQe)d=yX%sgxLF&(pAKVTa+?5 z(ILcm#Pd6p<|B4MLy}RSg=zz;n4&4vLV$E35ZkP;!^3*Ki5xY|Z z{fQHLO&3WzteG~+2z)qwlX$>%<{K#zH5sMBM1ZQ?G?gbB<8gVQH&+&;?f>J}=VhvF M-Y0JpEAsl;zX$Asy8r+H delta 1056 zcmYjQZ%9*76o2>4=Xz`UHr&%~MXhjKvCK@vg5e)5novYRlu(!$R!}CjD2UX`nPaZB zQ-tM*AR(hZC@(_H&>>}gkp}jqFV%-&LrWX|S+%;IyZ5SHxbMgB+~4_~ch0-7y@RxO zkfB9H6c=;pC4!k0iv!sz8&GOVF)=%wD*cBL<7k12%g42;S;@sXqu2rFq$Wm>+mwK+tjW}2UE;f zh{93JYRgm($2CcNA_>VXggoqZgc-PJX_a4TufjZIRy8FKUfD`wuv>P^np?VNZ1QK? z@*4EYUQ!Ix@@77f3zmEjDT1o}*L)%emKHp4KQyo|refajYzo4LRVv-iXjpiroi2m< zf(xE?*eYsf+zhxTpVT~onkTA8tvZs_8tJ!|lPJts3&{ugZrx!X(45A;r3GIMP-k-) zS70km(%Oh$i04DdwoN`Jrt7O_hgI!)n6p{ie3}7=!T1$6`>^2GN+aW9Zl(@x8I&Gz z-fAguAE*D9?veui8MHk{k7uawS`9<)s!^m($J zI4sUD#4f?Gy`ZQK?_$PS7BV|bTKXSZT zX?74^Ilb~JU(L-@+J*LS5r+^L5T7GX%u(8cc<%$HZxL@SP|D#HBZv;fT?tC75O2Xb zr^n_)wF_0;X1$3)A?`BVEf8_KZL82T9cD+kEV%u+9Y9DFbS3jfFRo>5p_W%F@ diff --git a/Project_1.3/Makefile b/Project_1.3/Makefile new file mode 100644 index 0000000..9e93f09 --- /dev/null +++ b/Project_1.3/Makefile @@ -0,0 +1,24 @@ +# Это комментарий, который говорит, что переменная CC указывает компилятор, используемый для сборки +CC= gcc +#Это еще один комментарий. Он поясняет, что в переменной CFLAGS лежат флаги, которые передаются компилятору +CFLAGS= -c -Wall + +default: build + +general: main.o functions.o + $(CC) ./out/main.o ./out/functions.o declare.h -o ./out/function_zeros_calculator -lm + + +main.o: main.c + $(CC) $(CFLAGS) main.c -o ./out/main.o + +functions.o: functions.c + $(CC) $(CFLAGS) functions.c -o ./out/functions.o + +clean: + rm -rf ./out/main.o ./out/functions.o + +build: general clean + +run: + ./out/function_zeros_calculator \ No newline at end of file diff --git a/Project_1.3/README b/Project_1.3/README new file mode 100644 index 0000000..6a1c669 --- /dev/null +++ b/Project_1.3/README @@ -0,0 +1,32 @@ +# Function Zeros Calculator + +## Описание +Эта программа предназначена для вычисления нулей функции на языке C в среде Linux. + +## Установка +1. Склонируйте репозиторий: git clone https://github.com/ada-dmitry/tmp_project.git +2. Перейдите в каталог проекта: cd /Project_1.2 + +## Использование +1. Соберите программу: make +2. Запустите программу: ./out/function_zeros_calculator +3. Введите необходимые параметры для вычисления нуля функции: a - ЛЕВАЯ граница отрезка + b - ПРАВАЯ граница отрезка, eps > 0 - точность вычисления корня(до 10^-6). + +## Замечания +1. Для корректной работы программы, необходимо вводить отрезок, на котором есть лишь один корень. +2. После вызова меню выбора действий (Ctrl+C) можно использовать как верхний регистр, так и нижний. +3. Не рекомендуется бесконечно вызывать Ctrl+C без выбора действия, это может повлечь ошибки + вследствие переполнения памяти. + + +## Обработка сигнала SIGINT + Программа обрабатывает сигнал SIGINT, что позволяет давать пользователю выбор действия +при нажатии сочетания клавиш Ctrl+C. + +## Авторы +Антипенко Дмитрий Андреевич [C22-712] - https://github.com/ada-dmitry/ +Кузнецов Даниил Евгеньевич [C22-712] +Никитин Михаил Андреевич [C22-712] +Ускова Екатерина Александровна [C22-712] + diff --git a/Project_1.3/declare.h b/Project_1.3/declare.h new file mode 100644 index 0000000..9e1b174 --- /dev/null +++ b/Project_1.3/declare.h @@ -0,0 +1,13 @@ +extern double a, b, eps, x, *pa, *pb, *px; +extern short method, *mth; +// Декларирование глобальных переменных, +// как внешних для последующего использования их во всей программе. +#define H 0.000001 + +double f(double x); +void ctrlc_handler(int signum); +void choose_path(); +void fork_method(); +void chord_method(); +void newton_method(); +double numerical_derivative(double x); \ No newline at end of file diff --git a/Project_1.3/functions.c b/Project_1.3/functions.c new file mode 100644 index 0000000..3a4dabc --- /dev/null +++ b/Project_1.3/functions.c @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include +#include + +#include "declare.h" + +double f(double x) // Функция, заданная пользователем, для которой происходит поиск корней. +{ + return x * x * x - 125; +} + +// Приближенное вычисление производной по методу конечных разностей +double numerical_derivative(double x) +{ + return (f(x + H) - f(x)) / H; +} + +void newton_method() +{ + *pb = *pa; + do + { + printf("%lf %lf\n", *pa, *pb); + *pa = *pb; + *pb = *pa - f(*pa) / numerical_derivative(*pa); + // Используем численно вычисленную производную + *px = *pb; + sleep(1); + } while (fabs(*pb - *pa) > eps && f(x) != 0); + return; +} + +void chord_method() +{ + *px = *pa; + while ((*pb - *pa) > eps && f(x) != 0) + { + // Находим точку пересечения хорды с осью x + *px = (*pa * f(*pb) - *pb * f(*pa)) / (f(*pb) - f(*pa)); + printf("%lf %lf\n", *pa, *pb); + // Проверяем знаки функции в точках a и x + if (f(*px) == 0) + break; + else if (f(*px) * f(*pa) < 0) + *pb = *px; + else + *pa = *px; + sleep(1); + } + return; +} + +void fork_method() // Функция поиска корней, использующая метод вилки. +{ + do + { + *px = (*pa + *pb) / 2; // метод деления отрезка пополам + + // Печать границ для отладки и для отслеживания хода вычислений + printf("%lf %lf\n", *pa, *pb); + + // Проверка, какой из отрезков [a, x] или [x, b] подходит под условие существования корня, + // т.е. различие знаков на границе. + if (f(*pa) * f(x) <= 0) + *pb = x; + else if (f(*pb) * f(x) <= 0) + *pa = x; + + sleep(1); // Принудительное ожидание программой, для возможности прерывания пользователем. + + } while (fabs(*pb - *pa) > eps && f(x) != 0); + return; +} + +void choose_path() // Функция выбора действия после вызова сигнала. +{ + char choice, *ch = &choice; + + struct termios term; // Задание структуры, определяющей терминал Linux. + + // Получение текущих настроек терминала + tcgetattr(0, &term); + + // Отключение символа ECHO + term.c_lflag &= ~ECHO; + + // Применение новых настроек терминала + tcsetattr(0, TCSANOW, &term); + + printf("\nПродолжить поиск корня?\n"); + printf("\nC - продолжить, A - закончить работу программы, \ +R - начать поиск на другом отрезке, M - выбрать другой способ решения: \n"); + + // Очистка стандартного потока ввода от "лишних" + __fpurge(stdin); + + do + { + *ch = getchar(); // Запись буквы, введенной пользователем в переменную choice. + + switch (*ch) + { + case 'C': // Выбор вида "Продолжить вычисление". + case 'c': + return; // Выход из функции без каких-либо изменений. + + case 'A': // Выбор вида "Завершить вычисление". + case 'a': + printf("\nКорень уравнения: %lf\n", *px); + printf("Работа программы завершена.\n"); + exit(0); // Принудительное завершение программы с выводом текущего приближения корня. + + case 'R': // Выбор вида "Продолжить вычисления с новым отрезком". + case 'r': + + // Включение символа ECHO + term.c_lflag |= ECHO; + + // Применение новых настроек терминала + tcsetattr(0, TCSANOW, &term); + + printf("Введите новые значения границ a и b: "); + + scanf("%lf%lf", pa, pb); + + if (f(*pa) * f(*pb) > 0) + { + printf("В указанных границах нуля функции не существует.\n"); + printf("Нажмите Ctrl+C и поменяйте границы\n"); + } + if (*pa == *pb) + { + if (f(*pa) == 0) + { + printf("\nКорень уравнения: %lf\n", *pa); + printf("Работа программы завершена.\n"); + exit(0); + } + else + { + printf("Нажмите Ctrl+C и поменяйте границы\n"); + } + } + return; + case 'M': + case 'm': + // Включение символа ECHO + term.c_lflag |= ECHO; + + // Применение новых настроек терминала + tcsetattr(0, TCSANOW, &term); + printf("Выберите метод вычисления корня:\ + 0 - метод вилки, 1 - метод хорд, 2 - метод касательных\n(По умолчанию: 0)\n"); + scanf("%hd", mth); + + printf("Введите новые значения границ a и b: "); + + scanf("%lf%lf", pa, pb); + + if (f(*pa) * f(*pb) > 0) + { + printf("В указанных границах нуля функции не существует.\n"); + printf("Нажмите Ctrl+C и поменяйте границы\n"); + } + if (*pa == *pb) + { + if (f(*pa) == 0) + { + printf("\nКорень уравнения: %lf\n", *pa); + printf("Работа программы завершена.\n"); + exit(0); + } + else + { + printf("Нажмите Ctrl+C и поменяйте границы\n"); + } + } + if (*mth == 0) + { + printf("Fork\n"); + fork_method(); + } + else if (*mth == 1) + { + printf("Chord\n"); + chord_method(); + } + else if (*mth == 2) + { + printf("Newton\n"); + newton_method(); + } + return; + + default: + printf("Ошибка ввода, повторная попытка...\n"); + } + } while (*ch != 'A' || *ch != 'R' || *ch != 'C' || *ch != 'a' || *ch != 'r' || *ch != 'c' || *ch != 'M' || *ch != 'm'); + + // Включение символа ECHO + term.c_lflag |= ECHO; + + // Применение новых настроек терминала + tcsetattr(0, TCSANOW, &term); +} + +void ctrlc_handler(int signum) // Функция, заменяющая стандартный алгоритм для сигнала SIGINT. +{ + printf("\nТекущее приближение: %lf\n", *px); + choose_path(); +} \ No newline at end of file diff --git a/Project_1.3/main.c b/Project_1.3/main.c new file mode 100644 index 0000000..1520639 --- /dev/null +++ b/Project_1.3/main.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include + +#include "declare.h" + +double a, b, eps, x, *pa, *pb, *px; +short method, *mth; + +int main() +{ + + double tmp; + method = 0; + mth = &method; + pa = &a; + pb = &b; + px = &x; + + struct sigaction sig; // Инициализация структуры, отвечающей за обработку сигнала. + // Замена стандартного алгоритма на необходимый для вызова меню действий. + sig.sa_handler = ctrlc_handler; + sig.sa_flags = 0; // Очистка флагов "на всякий случай". + sigemptyset(&sig.sa_mask); // Очистка маски "на всякий случай". + + if (sigaction(SIGINT, &sig, NULL) == -1) // Обработчик ошибок и инициализация сигнала SIGINT. + { + perror("sigaction"); + return 1; + } + + printf("Введите интервал [a, b] и точность eps: "); + scanf("%lf %lf %lf", pa, pb, &eps); + printf("Выберите метод вычисления корня:\ + 0 - метод вилки, 1 - метод хорд, 2 - метод касательных\n(По умолчанию: 0)\n"); + scanf("%hd", &method); + + if (*pa > *pb) // Если пользователь перепутал границы + { + printf("Границы указаны неверно, запуск задачи с исправленным условием\n"); + tmp = *pa; + *pa = *pb; + *pb = tmp; + } + + if (f(*pa) * f(*pb) > 0) + { + printf("В указанных границах нуля функции не существует.\n"); + printf("Нажмите Ctrl+C и поменяйте границы\n"); + } + if (eps < 0) // Если пользователь указал отрицательную точность + { + eps = eps * (-1); + printf("Точность отрицательна, условие приведено в порядок, запуск решения...\n"); + } + + if (*pa == *pb) + { + if (f(*pa) == 0) + { + printf("\nКорень уравнения: %lf\n", *pa); + printf("Работа программы завершена.\n"); + exit(0); + } + else + { + printf("Нажмите Ctrl+C и поменяйте границы\n"); + } + } + + if (*mth == 0) + { + printf("Fork\n"); + fork_method(); + } + else if (*mth == 1) + { + printf("Chord\n"); + chord_method(); + } + else if (*mth == 2) + { + printf("Newton\n"); + newton_method(); + } + + printf("\nКорень уравнения: %lf\n", *px); + printf("Работа программы завершена.\n"); + + return 0; +} + +// MEEEEEEEOW \ No newline at end of file diff --git a/Project_1.3/out/function_zeros_calculator b/Project_1.3/out/function_zeros_calculator new file mode 100755 index 0000000000000000000000000000000000000000..7cdb0c53864197a98be740a5465ba4527c7e5572 GIT binary patch literal 21168 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 literal 0 HcmV?d00001