Python и SymPy: проверяем вычисления

⏱ 30 мин · 🧩 заданий: 5

Зачем компьютер

Интегралы — тема, где легко ошибиться в знаке или коэффициенте. Компьютер помогает тремя способами:

  • строит графики — видно, что вы вообще считаете;
  • считает численно — получаем число, с которым можно сравнить свой ответ;
  • считает символьно — SymPy находит первообразные и проверяет преобразования.

Но компьютер не заменяет умения: чтобы понять, почему интеграл берётся, надо уметь считать руками. Используйте его как проверку, а не как решебник.

NumPy: численные расчёты

NumPy работает с массивами чисел. Функции np.sin, np.exp, np.log, np.sqrt применяются ко всему массиву сразу:

import numpy as np
import vis

x = np.linspace(0, np.pi, 9)       # 9 равноотстоящих точек от 0 до π
print(np.round(np.sin(x), 3))

xx = np.linspace(-np.pi, np.pi, 300)
vis.line(xx, {"sin x": np.sin(xx), "sin²x": np.sin(xx)**2, "(1 − cos 2x)/2": (1 - np.cos(2*xx)) / 2 + 0.03},
         title="Графики функций (третий сдвинут на 0,03, чтобы был виден)", xlabel="x")

Численно найти интеграл можно суммой прямоугольников или функцией np.trapz (метод трапеций):

import numpy as np

x = np.linspace(0, np.pi, 100001)
print("∫₀^π sin x dx ≈", np.trapz(np.sin(x), x))
x = np.linspace(0, 1, 100001)
print("∫₀¹ eˣ dx ≈", np.trapz(np.exp(x), x), "   точно: e − 1 =", np.e - 1)

SymPy: символьные вычисления

SymPy работает с формулами, а не с числами. Сначала объявляем символы, затем строим выражения:

import sympy as sp

x = sp.symbols("x")
f = x * sp.exp(x)

F = sp.integrate(f, x)                         # неопределённый интеграл (без + C!)
print("∫ x eˣ dx =", F)
print("проверка: F' =", sp.simplify(sp.diff(F, x)))
print("∫₀¹ x eˣ dx =", sp.integrate(f, (x, 0, 1)))        # определённый интеграл
print("∫₀^∞ e^(−x²) dx =", sp.integrate(sp.exp(-x**2), (x, 0, sp.oo)))
print("численно:", sp.N(sp.integrate(sp.sin(x) / x, (x, 0, 1)), 10))

Полезные функции:

Функция Что делает
sp.diff(f, x) производная
sp.integrate(f, x) первообразная (без +C)
sp.integrate(f, (x, a, b)) определённый интеграл; sp.oo — бесконечность
sp.simplify(e), sp.expand(e), sp.factor(e) упростить, раскрыть скобки, разложить на множители
sp.apart(e) разложить дробь на простейшие
e.subs(x, 2) подставить значение
sp.limit(e, x, 0) предел
sp.N(e) вычислить численно
sp.pi, sp.E, sp.oo \pi, e, \infty

Две особенности SymPy, о которых важно помнить:

  • log — натуральный логарифм, и в ответах SymPy обычно нет модуля: integrate(1/x, x) даёт log(x), хотя правильнее \ln|x| + C;
  • константу C SymPy не пишет — добавляйте её сами.

Главное правило: проверка дифференцированием

Первообразные одной функции могут выглядеть совершенно по-разному. Например, \int \sin x \cos x\,dx можно записать как \frac{\sin^2 x}{2}, как -\frac{\cos^2 x}{2} или как -\frac{\cos 2x}{4} — и всё это верно, потому что эти функции отличаются на константы.

import sympy as sp

x = sp.symbols("x")
answers = [sp.sin(x)**2 / 2, -sp.cos(x)**2 / 2, -sp.cos(2*x) / 4]
for F in answers:
    print(f"F = {str(F):16}  F' = {sp.simplify(sp.diff(F, x))}")
print("разности:", sp.simplify(answers[0] - answers[1]), ",", sp.simplify(answers[0] - answers[2]))

Все три производные одинаковы, а разности ответов — константы. Поэтому сравнивать ответ с задачником «по виду» бессмысленно: дифференцируйте. Так же проверяются ответы в этом курсе — численно, с точностью до константы.

Итог

  • NumPy считает численно: графики, суммы, np.trapz.
  • SymPy считает символьно: diff, integrate, simplify, apart, limit; без +C и часто без модуля в логарифме.
  • Первообразную проверяют дифференцированием; разные по виду ответы могут отличаться лишь на константу.

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Один вариант ответа

Вы нашли первообразную F(x) для f(x). Как надёжнее всего проверить ответ?

Задание 2 Один вариант ответа

SymPy выдал integrate(1/x, x) = log(x). Что важно помнить?

Задание 3 Программа на Python

Проверка первообразной. Напишите функцию is_antiderivative(F, f, xs): она получает две функции Python (F — кандидат в первообразные, f — подынтегральная функция) и список точек xs. Для каждой точки посчитайте численную производную \frac{F(x + h) - F(x - h)}{2h} при h = 10^{-5} и сравните с f(x): верните True, если во всех точках отличие меньше 10^{-4}.

Какие тесты проверяют код (1)
import math
xs = [0.5, 1.0, 1.7, 2.3]
assert is_antiderivative(lambda x: x**3 / 3, lambda x: x**2, xs)
assert is_antiderivative(lambda x: -math.cos(x) + 5, math.sin, xs), "Константа не важна"
assert not is_antiderivative(lambda x: x**3, lambda x: x**2, xs), "x³ — не первообразная x²"
assert not is_antiderivative(lambda x: math.log(x), lambda x: 1 / x**2, xs)

Задание 4 Программа на Python

Интегрируем на SymPy. Напишите функцию antiderivative(expr_text): она получает строку с выражением от x (например, "x*exp(x)"), превращает её в выражение SymPy (sp.sympify), находит первообразную (sp.integrate) и возвращает её строкой (str(...)).

Какие тесты проверяют код (1)
import sympy as sp
x = sp.symbols("x")
for text in ["x**2", "x*exp(x)", "cos(x)**2", "1/(x**2 + 1)"]:
    F = antiderivative(text)
    assert isinstance(F, str), "Верните строку"
    assert sp.simplify(sp.diff(sp.sympify(F), x) - sp.sympify(text)) == 0, f"Производная ответа для {text} не совпадает с ним"

Задание 5 Программа на Python

Площадь численно. Напишите функцию area(f, a, b, n), которая приближает \int_a^b f(x)\,dx суммой n средних прямоугольников: отрезок делится на n равных частей шириной h = \frac{b - a}{n}, высота каждого прямоугольника — значение f в середине части. Можно использовать NumPy (f принимает массив).

Какие тесты проверяют код (1)
import numpy as np
assert abs(area(lambda x: x**2, 0, 1, 1000) - 1/3) < 1e-6, "∫₀¹ x² dx = 1/3"
assert abs(area(np.sin, 0, np.pi, 1000) - 2) < 1e-5, "∫₀^π sin x dx = 2"
assert abs(area(lambda x: x, 0, 2, 1) - 2) < 1e-12, "Для линейной функции средние прямоугольники точны даже при n = 1"
assert abs(area(lambda x: x**2, 0, 1, 2) - 0.3125) < 1e-12, "При n = 2 середины — 0.25 и 0.75"

Войдите, чтобы отмечать пройденные уроки.