Метод Эйлера: первый шаг в мир ОДУ
Урок про метод Эйлера — простейший способ численно решить дифференциальное уравнение, шагая по касательной.
Метод Эйлера решает
y' = f(t, y)с условиемy(t₀)=y₀, делая шаги по касательной:y_{n+1} = y_n + h·f(t_n, y_n).
Что значит «решить ОДУ численно»
Дифференциальное уравнение y' = f(t, y) задаёт скорость изменения y в каждой точке, а нам нужна сама функция y(t). Аналитически это удаётся редко; численно — почти всегда. Идея проста: в начальной точке мы знаем и y, и наклон y' = f(t₀, y₀). Сделаем маленький шаг h по этой касательной — получим приближённое y в точке t₀+h. Там пересчитаем наклон и шагнём снова. Так, шаг за шагом, рисуем траекторию решения. Это и есть явный метод Эйлера.
def эйлер(f, t0, y0, h, n):
t, y = t0, y0
точки = [(t, y)]
for _ in range(n):
y = y + h * f(t, y) # шаг по касательной
t = t + h
точки.append((t, y))
return точки
import math
# y' = y, y(0) = 1 -> точное решение y = e^t
for t, y in эйлер(lambda t, y: y, 0.0, 1.0, 0.25, 4):
print(f"t={t:.2f} Эйлер={y:.6f} точное={math.exp(t):.6f} "
f"ошибка={abs(y - math.exp(t)):.4f}")
Вывод:
t=0.00 Эйлер=1.000000 точное=1.000000 ошибка=0.0000 t=0.25 Эйлер=1.250000 точное=1.284025 ошибка=0.0340 t=0.50 Эйлер=1.562500 точное=1.648721 ошибка=0.0862 t=0.75 Эйлер=1.953125 точное=2.117000 ошибка=0.1639 t=1.00 Эйлер=2.441406 точное=2.718282 ошибка=0.2769
Эйлер уверенно растёт вместе с решением, но систематически отстаёт: касательная всегда чуть «недотягивает» до выпуклой экспоненты, и ошибки копятся. К t=1 отставание уже 0.28 — заметно. Виноват крупный шаг.
Первый порядок точности
Метод Эйлера имеет первый порядок: глобальная ошибка пропорциональна h. Уменьшим шаг вдвое — ошибка упадёт примерно вдвое. Это медленно: для одной дополнительной цифры нужно в 10 раз больше шагов. Поэтому на практике чистый Эйлер почти не используют для точных расчётов — но он бесценен как понятная отправная точка и кирпичик для более умных методов (Рунге-Кутты).
точное решение (кривая)
/
/ • y2 ← Эйлер отстаёт: каждый шаг
/ / идёт по касательной (прямой)
/ • y1 и «срезает» выпуклость
/•/
y0
t0 t1 t2 → ошибка накапливается с каждым шагом
Неявный Эйлер и устойчивость
Есть вариант — неявный (обратный) метод Эйлера: y_{n+1} = y_n + h·f(t_{n+1}, y_{n+1}). Наклон берётся в конце шага, а не в начале. Неизвестное y_{n+1} теперь в обеих частях — приходится решать уравнение на каждом шаге (например, Ньютоном). Зачем такая морока? Ради устойчивости. Для «убегающих вниз» решений вроде y' = −15y явный Эйлер при крупном шаге разносит ответ в бесконечность, а неявный остаётся устойчивым при любом шаге.
# y' = -15y, y(0)=1. Точное: y = e^(-15t), быстро гаснет к нулю.
import math
def явный(h, n): # y_{n+1} = y_n + h*(-15 y_n)
y = 1.0
for _ in range(n):
y = y + h * (-15 * y)
return y
def неявный(h, n): # y_{n+1} = y_n / (1 + 15h) -- решено аналитически
y = 1.0
for _ in range(n):
y = y / (1 + 15 * h)
return y
print("шаг h=0.25 (крупный):")
print(f" явный Эйлер: y(1) = {явный(0.25, 4):.4f} (точное ≈ 0)")
print(f" неявный Эйлер: y(1) = {неявный(0.25, 4):.6f} (точное ≈ 0)")
Вывод:
шаг h=0.25 (крупный): явный Эйлер: y(1) = 57.1914 (точное ≈ 0) неявный Эйлер: y(1) = 0.001964 (точное ≈ 0)
Картина драматична: точное решение стремится к нулю, неявный Эйлер это уважает (0.002, близко к нулю), а явный при шаге 0.25 взрывается до 57 и дальше уходит в бесконечность. Это не ошибка кода — это неустойчивость явного метода на «жёстком» уравнении (об этом — следующий урок).
Как работает под капотом
Локальная ошибка одного шага Эйлера — ~ h²·y''/2 (отброшенный член Тейлора), но за 1/h шагов они накапливаются в глобальную ~ h — отсюда первый порядок. Устойчивость же — отдельное свойство: для тестового уравнения y'=λy явный Эйлер устойчив лишь при |1 + hλ| ≤ 1, то есть требует малого h при большом |λ|. Неявный Эйлер устойчив при любом h (A-устойчивость) — потому и нужен для жёстких задач. Так в одном простом методе видны обе ключевые оси численного решения ОДУ: точность (порядок) и устойчивость.
Частые ошибки
- Думать, что малая ошибка за шаг = малая ошибка решения. Ошибки накапливаются; глобальный порядок Эйлера всего первый.
- Применять явный метод к жёсткому уравнению с крупным шагом. Получите взрыв решения; нужен неявный метод или крошечный шаг.
- Использовать чистый Эйлер для точных расчётов. Первый порядок слишком груб; берите RK4 (следующий урок).
Итоги
- Явный Эйлер:
y_{n+1} = y_n + h·f(t_n, y_n)— шаг по касательной, первый порядок (ошибка ∝h). - Неявный Эйлер берёт наклон в конце шага; решает уравнение на каждом шаге, зато устойчив при любом
h. - Точность и устойчивость — разные свойства: явный метод может быть точным, но неустойчивым.
- Эйлер — фундамент для понимания, но для практики груб; дальше — Рунге-Кутты.