Загрузка данных
import math
import numpy as np
import matplotlib.pyplot as plt
# =========================
# Вариант 20
# f(x) = x*sin(x)*arctg(x)
# [a, b] = [1, 2]
# Nmax = 10^6
# Критерии остановки:
# 1) для бисекции: |b-a| < eps_x
# 2) для касательных: |x_(n+1)-x_n| < eps_x
# 3) дополнительно: |f(x_(n+1)) - f(x_n)| < eps_f = 10^-15
# =========================
a = 1.0
b = 2.0
eps_x = 1e-14
eps_f = 1e-15
Nmax = 10**6
def f(x):
return x * math.sin(x) * math.atan(x)
def df(x):
return math.sin(x) * math.atan(x) + x * math.cos(x) * math.atan(x) + x * math.sin(x) / (1 + x * x)
def bisection_method(a, b):
fa = f(a)
fb = f(b)
print('ПРОВЕРКА ДЛЯ БИСЕКЦИИ:')
print(f'f(a) = f({a}) = {fa:.16f}')
print(f'f(b) = f({b}) = {fb:.16f}')
if fa * fb > 0:
print('
Метод бисекции неприменим, потому что на [a,b] нет смены знака.')
print('То есть f(a) * f(b) > 0.')
return None, []
print('
Смена знака есть, бисекцию можно применять.
')
steps = []
for n in range(1, Nmax + 1):
c = (a + b) / 2.0
fc = f(c)
steps.append((n, a, b, c, fa, fb, fc, abs(b - a)))
if abs(b - a) < eps_x:
print(f'Корень найден методом бисекции: x ≈ {c:.16f}')
print(f'Число итераций: {n}')
return c, steps
if fa * fc <= 0:
b = c
fb = fc
else:
a = c
fa = fc
return c, steps
def newton_method(x0):
print('
ПРОВЕРКА ДЛЯ МЕТОДА КАСАТЕЛЬНЫХ:')
print(f'Начальное приближение x0 = {x0}')
steps = []
x = x0
for n in range(1, Nmax + 1):
fx = f(x)
dfx = df(x)
if abs(dfx) < 1e-16:
print('Производная слишком мала, метод остановлен.')
return None, steps
x_next = x - fx / dfx
delta_x = abs(x_next - x)
delta_f = abs(f(x_next) - f(x))
steps.append((n, x, fx, dfx, x_next, delta_x, delta_f))
if delta_x < eps_x or delta_f < eps_f:
print(f'Корень найден методом касательных: x ≈ {x_next:.16f}')
print(f'Число итераций: {n}')
print(f'|x_(n+1)-x_n| = {delta_x:.3e}')
print(f'|f(x_(n+1)) - f(x_n)| = {delta_f:.3e}')
return x_next, steps
x = x_next
return x, steps
def draw_function():
xs = np.linspace(a, b, 600)
ys = [f(x) for x in xs]
plt.figure(figsize=(10, 6))
plt.plot(xs, ys, label='f(x) = x*sin(x)*arctg(x)', color='blue', linewidth=2)
plt.axhline(0, color='black', linewidth=1)
plt.axvline(a, color='gray', linestyle='--', alpha=0.5)
plt.axvline(b, color='gray', linestyle='--', alpha=0.5)
plt.scatter([a, b], [f(a), f(b)], color='red', zorder=5, label='Концы интервала')
plt.title('График функции на [1, 2]')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, alpha=0.3)
plt.legend()
plt.show()
def draw_bisection_visualization(steps):
if not steps:
print('
Для варианта 20 визуализация бисекции отсутствует,')
print('потому что метод бисекции неприменим: нет смены знака на [1,2].')
return
xs = np.linspace(a, b, 600)
ys = [f(x) for x in xs]
plt.figure(figsize=(10, 6))
plt.plot(xs, ys, color='blue', linewidth=2, label='f(x)')
plt.axhline(0, color='black', linewidth=1)
for i, step in enumerate(steps[:10]):
n, left, right, mid, fa, fb, fm, width = step
plt.axvline(mid, linestyle='--', alpha=0.4, label=f'c{i + 1}' if i == 0 else None)
plt.scatter(mid, fm, color='red', s=25)
plt.title('Метод бисекции: середины отрезков')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, alpha=0.3)
plt.legend()
plt.show()
def draw_newton_visualization(x0, tangent_steps=6):
xs = np.linspace(a, b, 600)
ys = [f(x) for x in xs]
plt.figure(figsize=(10, 6))
plt.plot(xs, ys, color='blue', linewidth=2, label='f(x) = x*sin(x)*arctg(x)')
plt.axhline(0, color='black', linewidth=1)
x = x0
for i in range(tangent_steps):
fx = f(x)
dfx = df(x)
if abs(dfx) < 1e-16:
break
x_line = np.linspace(max(a, x - 0.4), min(b, x + 0.4), 100)
y_line = fx + dfx * (x_line - x)
plt.plot(x_line, y_line, '--', linewidth=1.5, label=f'Касательная {i + 1}')
plt.scatter(x, fx, color='red', zorder=5)
x_next = x - fx / dfx
if a <= x_next <= b:
plt.scatter(x_next, 0, color='green', zorder=5)
delta_x = abs(x_next - x)
delta_f = abs(f(x_next) - f(x)) if abs(x_next) < 1e6 else float('inf')
if delta_x < eps_x or delta_f < eps_f:
break
x = x_next
plt.title('Метод касательных: все касательные из начальной точки')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, alpha=0.3)
plt.legend()
plt.show()
# =========================
# ОСНОВНАЯ ЧАСТЬ
# =========================
print('ВАРИАНТ 20')
print('f(x) = x*sin(x)*arctg(x)')
print(f'Интервал: [{a}, {b}]')
print(f'Nmax = {Nmax}')
print(f'eps_x = {eps_x}')
print(f'eps_f = {eps_f}')
print('-' * 60)
fa = f(a)
fb = f(b)
print(f'f({a}) = {fa:.16f}')
print(f'f({b}) = {fb:.16f}')
bis_steps = []
newton_steps = []
if fa * fb > 0:
print('
На отрезке [1,2] нет смены знака.')
print('Следовательно, корня на заданном интервале нет.')
print('Метод бисекции неприменим.')
print('Метод касательных можно только визуализировать,')
print('но корень на [1,2] эта функция не имеет.')
else:
root_bis, bis_steps = bisection_method(a, b)
root_newton, newton_steps = newton_method((a + b) / 2)
print('
Построение графиков...')
draw_function()
draw_bisection_visualization(bis_steps)
draw_newton_visualization(1.5, tangent_steps=6)