Решение алгебраических и трансцендентных уравнений методом хорд и методом касательных (Ньютона)
ОП.10 Численные методы · Специальность 09.02.07 «Информационные системы и программирование»
Объём: 2 академических часа
На лекции вы узнали, что методы хорд и Ньютона работают в 5–10 раз быстрее бисекции. Теперь проверим это на практике: решим уравнения вручную, запрограммируем оба метода на Python и измерим, насколько они быстрее.
После выполнения этой практической работы вы должны:
Формат сдачи: Отчёт в формате PDF или Word, содержащий скриншоты ручных расчётов, исходный код программ на Python с комментариями, скриншоты результатов выполнения и заполненную таблицу сравнения.
Перед началом работы освежим формулы и алгоритмы.
Если на концах отрезка [a, b] функция имеет разные знаки, новое приближение корня:
c = a − f(a) · (b − a) / (f(b) − f(a))
Затем сужаем отрезок: [a, c] или [c, b] — где функция меняет знак.
Итерационная формула:
xₙ₊₁ = xₙ − f(xₙ) / f'(xₙ)
Нужна производная f'(x). Если её сложно найти, используют численную производную: f'(x) ≈ (f(x+h) − f(x−h)) / (2h).
Для обоих методов: |xₙ₊₁ − xₙ| < ε или |f(xₙ)| < ε.
Напоминание: всегда ставьте ограничение на число итераций (max_iter), иначе при неудачном старте метод Ньютона может «разлететься» и программа зависнет.
Преподаватель выдаёт вам один из шести вариантов. Для каждого варианта указаны функция, её производная и отрезок локализации.
| Вариант | Уравнение f(x) = 0 | Производная f'(x) | Отрезок [a, b] |
|---|---|---|---|
| 1 | x³ − x − 1 = 0 |
3x² − 1 |
[1, 2] |
| 2 | cos(x) − x = 0 |
−sin(x) − 1 |
[0, 1] |
| 3 | e^x − 3x = 0 |
e^x − 3 |
[0, 1] |
| 4 | x³ − 2x − 5 = 0 |
3x² − 2 |
[2, 3] |
| 5 | ln(x) + x − 3 = 0 |
1/x + 1 |
[2, 3] |
| 6 | x·sin(x) − 1 = 0 |
sin(x) + x·cos(x) |
[1, 2] |
Точность для всех вариантов: ε = 10⁻⁶ (в коде 1e-6). Это значит, что ошибка должна быть меньше одной миллионной.
Прежде чем писать код, посмотрите на рисунок. Здесь на одном графике показаны стратегии трёх методов для поиска одного и того же корня.
Рисунок 1. Бисекция идёт «шаг за шагом», хорда — прямолинейно, Ньютон — почти сразу в цель
Ваша задача: построить такой же график для своего уравнения, но с траекторией только метода Ньютона. Это задание №4.
Выполните 3 итерации метода хорд для своего варианта на бумаге. Записывайте все промежуточные значения — они пойдут в отчёт.
f(a) · f(b) < 0.c по формуле хорды.f(c) и замените тот конец отрезка, с которым знак совпал.x³ − x − 1 = 0 на [1, 2]| Шаг | a | b | c | f(c) |
|---|---|---|---|---|
| 0 | 1.0000 | 2.0000 | — | f(1)=−1; f(2)=5 |
| 1 | 1.0000 | 2.0000 | 1.1667 | −0.5787 |
| 2 | 1.1667 | 2.0000 | 1.2531 | −0.2850 |
| 3 | 1.2531 | 2.0000 | 1.2934 | −0.1280 |
Что сдать: таблицу с 3 итерациями и вывод: «За 3 шага приближение сместилось с 1.1667 до 1.2934. Точный корень ≈ 1.3247».
Для того же уравнения сделайте 3 итерации метода Ньютона. Сравните с заданием №1 — насколько быстрее?
x³ − x − 1 = 0, производная 3x² − 1Стартуем с x₀ = 1 (конец отрезка, где f(1) = −1).
| Шаг | xₙ | f(xₙ) | f'(xₙ) | xₙ₊₁ |
|---|---|---|---|---|
| 0 | 1.0000 | −1.0000 | 2.0000 | 1.5000 |
| 1 | 1.5000 | 0.8750 | 5.7500 | 1.3478 |
| 2 | 1.3478 | 0.1012 | 4.4496 | 1.3251 |
| 3 | 1.3251 | 0.0019 | 4.2680 | 1.3247 |
Сравнение: метод Ньютона за 4 шага дошёл до 1.3247 (4 верных знака), а метод хорд за 3 шага дал только 1.2934 (2 верных знака). Вот вам квадратичная сходимость на практике!
Что сдать: таблицу с 3 итерациями и вывод-сравнение с заданием №1.
Реализуйте метод хорд на Python. Замените функцию и отрезок на свой вариант.
def f(x):
"""ВАШ ВАРИАНТ. Пример для варианта 1."""
return x**3 - x - 1
def chord_method(a, b, epsilon, max_iter=100):
"""Метод хорд. Возвращает (корень, число шагов)."""
if f(a) * f(b) >= 0:
raise ValueError("f(a) и f(b) одного знака!")
step = 0
while step < max_iter:
c = a - f(a) * (b - a) / (f(b) - f(a))
step += 1
print(f"Шаг {step:2d}: c = {c:.10f}, f(c) = {f(c):+.3e}")
if abs(f(c)) < epsilon or abs(b - a) < epsilon:
return c, step
if f(a) * f(c) < 0:
b = c
else:
a = c
return (a + b) / 2, step
# Запуск для варианта 1
root, steps = chord_method(1, 2, 1e-6)
print(f"\n🎯 Корень: x ≈ {root:.10f}")
print(f"Шагов: {steps}")
print(f"Проверка: f(x) = {f(root):.2e}")
Что сдать: скриншот консоли с выводом всех итераций и итоговым корнем. Сравните число шагов с ручным расчётом (должно совпасть).
Реализуйте метод Ньютона. Нужна производная — она указана в таблице вариантов.
def f(x):
return x**3 - x - 1 # ВАШ ВАРИАНТ
def df(x):
return 3*x**2 - 1 # ВАШ ВАРИАНТ
def newton_method(x0, epsilon, max_iter=50):
"""Метод Ньютона. Возвращает (корень, число шагов)."""
x = x0
for n in range(max_iter):
fx = f(x)
dfx = df(x)
if abs(dfx) < 1e-12:
print("⚠️ Производная близка к нулю!")
return None, n
x_new = x - fx / dfx
print(f"Шаг {n+1:2d}: x = {x_new:.10f}, f(x) = {f(x_new):+.3e}")
if abs(x_new - x) < epsilon:
return x_new, n + 1
x = x_new
return x, max_iter
# Запуск для варианта 1
root, steps = newton_method(1.0, 1e-6)
print(f"\n🎯 Корень: x ≈ {root:.10f}")
print(f"Шагов: {steps}")
print(f"Проверка: f(x) = {f(root):.2e}")
Реализуйте метод Ньютона без аналитической производной, используя численную:
def df_numeric(x, h=1e-7):
return (f(x + h) - f(x - h)) / (2 * h)
Замените df(x) на df_numeric(x) и убедитесь, что корень тот же. Сколько шагов добавилось?
Что сдать: скриншоты консоли для обоих вариантов (с аналитической и численной производной) + вывод о разнице в числе шагов.
Постройте график функции и покажите на нём, как метод Ньютона «прыгает» к корню.
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return x**3 - x - 1 # ВАШ ВАРИАНТ
def df(x):
return 3*x**2 - 1 # ВАШ ВАРИАНТ
# Массив точек для кривой
x_curve = np.linspace(0.5, 2.5, 400)
y_curve = f(x_curve)
plt.figure(figsize=(10, 6))
plt.plot(x_curve, y_curve, 'b-', linewidth=2, label='f(x)')
plt.axhline(0, color='black', linewidth=1)
# Итерации Ньютона
x = 1.0
points_x, points_y = [x], [f(x)]
for _ in range(5):
x = x - f(x) / df(x)
points_x.append(x)
points_y.append(f(x))
# Рисуем касательные
for i in range(len(points_x) - 1):
x0, y0 = points_x[i], points_y[i]
slope = df(x0)
x_line = np.array([x0 - 0.3, x0 + 0.3])
y_line = y0 + slope * (x_line - x0)
plt.plot(x_line, y_line, 'r--', alpha=0.5, linewidth=1)
# Точки старта и корня
plt.plot(points_x[0], points_y[0], 'go', markersize=10, label='старт')
plt.plot(points_x[-1], points_y[-1], 'r*', markersize=15, label='корень')
plt.grid(True, alpha=0.3)
plt.legend()
plt.title('Метод Ньютона: касательные ведут к корню')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.show()
Что сдать: скриншот графика с подписью «Рисунок 1. Траектория метода Ньютона для варианта N». Обратите внимание, как касательные «сходятся» к точке пересечения с осью Ox.
Самое интересное: запустите все три метода на одном уравнении и сравните их скорость.
import time
def bisection(f, a, b, eps, max_iter=200):
steps = 0
while abs(b - a) > eps and steps < max_iter:
c = (a + b) / 2
steps += 1
if f(a) * f(c) < 0:
b = c
else:
a = c
return (a + b) / 2, steps
# --- замеряем время ---
results = {}
t0 = time.perf_counter()
root, steps = bisection(f, 1, 2, 1e-6)
results['Бисекция'] = (root, steps, time.perf_counter() - t0)
t0 = time.perf_counter()
root, steps = chord_method(1, 2, 1e-6)
results['Хорды'] = (root, steps, time.perf_counter() - t0)
t0 = time.perf_counter()
root, steps = newton_method(1.0, 1e-6)
results['Ньютон'] = (root, steps, time.perf_counter() - t0)
print(f"\n{'Метод':<12} {'Корень':<16} {'Шагов':<8} {'Время (мкс)':<12}")
print("-" * 50)
for name, (r, s, t) in results.items():
print(f"{name:<12} {r:<16.10f} {s:<8} {t*1e6:<12.1f}")
| Метод | Найденный корень | Число шагов | Время (мкс) |
|---|---|---|---|
| Бисекция | |||
| Хорды | |||
| Ньютон |
Ожидаемый результат: бисекция ~20 шагов, хорды ~10, Ньютон ~5. Время Ньютона обычно в 2–3 раза меньше времени бисекции (из-за меньшего числа шагов, но чуть более сложной арифметики на каждом).
Следуйте чек-листу, чтобы работа была принята с первого раза:
Формат файла: PDF или DOCX. Имя файла: Фамилия_Практика3_ЧисленныеМетоды.pdf.
f(x) и f''(x) одного знака.max_iter. Всегда ставьте лимит итераций.df(x) == 0 в какой-то точке. Добавьте проверку if abs(df(x)) < 1e-12.[a, b] с одинаковыми знаками на концах.f(a) * f(b) < 0.float через ==.abs(x_new - x) < eps.df_numeric(x) ≈ df(x).Золотое правило: если метод «сломался» — не паникуйте. Проверьте три вещи: производную, начальное приближение и наличие max_iter. В 90% случаев проблема в одном из этих трёх мест.
Вы научились решать уравнения не «в лоб»,
а прицельно — используя форму графика.
Теперь вы понимаете, почему метод Ньютона — стандарт в инженерных пакетах, машинном обучении и финансовых системах. Сохраните отчёт и подготовьте его к сдаче.
Отличная работа! Следующий раздел — решение систем линейных уравнений (СЛАУ).
💡 Подсказка: используйте клавиши ← → на клавиатуре для переключения слайдов