diff --git a/lab_1/main.py b/lab_1/main.py index 49910b8..9024848 100644 --- a/lab_1/main.py +++ b/lab_1/main.py @@ -1,90 +1,89 @@ import numpy as np import math from sympy import diff, symbols, cos, sin + left_border = -8 right_border = 2 eps = 1e-5 -# определение функция + def f(x): return 10 * math.cos(x) - 0.1 * x**2 -# определение производной + def df(x): return -10 * math.sin(x) - 0.2 * x -# процедура отделения корней + def tabulation_approach(a, b, step): - intervals = [] # Список для хранения отрезков изменения знака - sign_changes = 0 # счетчик изменений знака + intervals = [] + sign_changes = 0 current_x = a while current_x <= b: - current_y = f(current_x) # Значение функции в текущей точке - next_x = current_x + step # Переход к следующей точке с шагом step - next_y = f(next_x) # Значение функции в следующей точке + current_y = f(current_x) + next_x = current_x + step + next_y = f(next_x) - if current_y * next_y <= 0: # Проверка на изменение знака + if current_y * next_y <= 0: intervals.append((current_x, next_x)) sign_changes += 1 - current_x = next_x # Переопределение текущей точки для следующей итерации + current_x = next_x print(f"Отрезки изменения знака: {', '.join(map(lambda interval: f'[{interval[0]:.4f}, {interval[1]:.4f}]', intervals))}") print(f"Количество отрезков изменения знака: {sign_changes}") -# Метод бисекции -def bisection (a,b,n, eps): # отрезок от a до b делим на n частей, погрешность eps - assert a!=0, 'a равно 0' + +def bisection(a, b, n, eps): + assert a!=0, 'a равно 0' assert b!=0, 'b равно 0' - count = 0 # счетчик количества итераций для достижения точности epsilon - # сначала отделим корни - setka=np.linspace(a, b, n) - # далее уточним корни - for x,y in zip(setka, setka[1:]): - if f(x) * f(y) > 0: # если на отрезке нет корня, смотрим следующий + count = 0 + setka = np.linspace(a, b, n) + for x, y in zip(setka, setka[1:]): + if f(x) * f(y) > 0: continue root = None - while ( abs(f(y)-f(x)) )>eps: # пока отрезок больше заданной погрешности, выполняем нижестоящие операции: - mid = (y+x)/2 # получаем середину отрезка - if f(mid) == 0 or f(mid) eps: + mid = (y + x) / 2 + if f(mid) == 0 or f(mid) < eps: + root = mid break - elif (f(mid) * f(x)) < 0: # иначе если произведение функции в середине отрезка на функцию в т. а <0 - y = mid # серединой становится точка b + elif (f(mid) * f(x)) < 0: + y = mid else: - x = mid #в другом случае - точка а + x = mid count += 1 if root: yield root print("Количество шагов для достижения точности epsilon:", count) -# Реализация метода Ньютона для нахождения корня функции + def newton_method(initial_guess, eps): - x0 = initial_guess # начальное предположение - count = 0 # счетчик итераций + x0 = initial_guess + count = 0 while True: - x1 = x0 - f(x0) / df(x0) # основная формула метода Ньютона + x1 = x0 - f(x0) / df(x0) count += 1 - if abs(x1 - x0) < eps: # проверка точности + if abs(x1 - x0) < eps: break - x0 = x1 # изменение предположения + x0 = x1 return x1, count -# Модифицированный метод Ньютона -def modified_newton(f, df, x0, eps = 1e-5, max_iter=1000): + +def modified_newton(f, df, x0, eps=1e-5, max_iter=1000): x = x0 iteration = 0 while True: - x_new = x - f(x) / df(x0) # обновление значения x по формуле Ньютона + x_new = x - f(x) / df(x0) iteration += 1 - # проверка условия сходимости или достижения максимального количества итераций if abs(x_new - x) < eps or iteration >= max_iter: break x = x_new return x_new, iteration -def secant_method(f, x0, x1, eps = 1e-5, max_iter=100): + +def secant_method(f, x0, x1, eps=1e-5, max_iter=100): iterations = 0 while iterations < max_iter: @@ -98,33 +97,27 @@ def secant_method(f, x0, x1, eps = 1e-5, max_iter=100): iterations += 1 raise Exception("Не удалось найти корень методом секущих") + print("Функция f(x): 10 * cos(x) - 0.1 * x**2") -print("Параметры:\nЛевая граница: {}\nПравая граница: {}\nТочность: {}".format(left_border, right_border, eps)) +print(f"Параметры:\nЛевая граница: {left_border}\nПравая граница: {right_border}\nТочность: {eps}") print("Метод бисекции:") -tabulation_approach(-8, 2, 0.1) -res = list(bisection(-8,2,1000, 0.00001)) +tabulation_approach(left_border, right_border, 0.1) +res = list(bisection(left_border, right_border, 1000, 0.00001)) print('Корни по методу бисекции находятся в точках:') print(', '.join(map(lambda x: f'{x:.4f}', res))) print("Метод Ньютона:") -initial_guess = (left_border+right_border)/2 # начальное предположение - +initial_guess = (left_border + right_border) / 2 root, iterations = newton_method(initial_guess, eps) - print(f"Корень методом Ньютона: {root:.6f}") print(f"Количество итераций: {iterations}") - print("Модифицированный метод Ньютона:") x0 = 1.5 solution, iterations = modified_newton(f, df, x0) - print("Корень: {:.7f}".format(solution)) print("Количество итераций:", iterations) print("Метод секущих: ") x0 = 1 x1 = 2 - solution_secant, iterations_secant = secant_method(f, x0, x1) print("Корень уравнения {:.7f}:".format(solution_secant)) print("Количество итераций:", iterations_secant) - -