</>
Тема 2 из 5

Уравнения

Решение уравнений — одна из главных возможностей SymPy. Ответ получается точным: дроби остаются дробями, корни — корнями.

Уравнение — это Eq или выражение

Знак = в Python занят присваиванием, а == сравнивает выражения как объекты. Поэтому уравнение записывают так:

from sympy import symbols, Eq, solve

x = symbols("x")
print(solve(Eq(3 * x - 1, 5), x))   # [2]
print(solve(3 * x - 6, x))          # [2] — «выражение = 0»

Если передать просто выражение, SymPy считает, что оно равно нулю. Уравнение из текста "лев = прав" удобно превратить в выражение sympify(лев) - sympify(прав).

solve

print(solve(x ** 2 - 2, x))                  # [-sqrt(2), sqrt(2)]
print(solve(x ** 2 + 4, x))                  # [-2*I, 2*I]
print(solve(x ** 3 - 1, x))                  # [1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2]
  • результат — список корней (каждый корень один раз, даже если он кратный);
  • по умолчанию ищутся и комплексные корни; I — мнимая единица;
  • если объявить x = symbols("x", real=True), комплексные корни отбросятся.

Похожая функция solveset(выражение, x, domain=S.Reals) возвращает множество решений — она честнее сообщает, когда решений бесконечно много, например у sin x = 0.

Корни многочленов

Для многочленов есть специальные инструменты:

from sympy import Poly, roots, real_roots

p = Poly(x ** 3 - 3 * x + 1, x)
print(p.degree(), p.all_coeffs())   # 3 [1, 0, -3, 1]
print(roots(x ** 2 - 2 * x + 1))    # {1: 2} — корень 1 кратности 2
print(real_roots(x ** 3 - 2))       # [CRootOf(x**3 - 2, 0)]

real_roots возвращает действительные корни с повторами по кратности в порядке возрастания. Корень, который нельзя записать через радикалы, SymPy хранит как CRootOf — это тоже точное число, и float(r) даст его приближённое значение.

Системы уравнений

Уравнения и неизвестные передаются списками:

x, y = symbols("x y")
print(solve([x + y - 10, x - y - 2], [x, y]))               # {x: 6, y: 4}
print(solve([x ** 2 + y ** 2 - 25, x - 3], [x, y]))         # [(3, -4), (3, 4)]

Форма ответа зависит от задачи: словарь для одного решения, список кортежей для нескольких. С параметром dict=True ответ всегда одинаковый — список словарей, по одному на решение:

for s in solve([x ** 2 + y ** 2 - 25, x - 3], [x, y], dict=True):
    print(s[x], s[y])

У выражений есть свойство .is_real — True, если число действительное. Им удобно отбирать нужные решения.

Если точного решения нет (например, cos x = x), используют численный поиск: nsolve(cos(x) - x, x, 1) — корень рядом с 1.

Итог

  • Eq(a, b) или выражение a - b — уравнение;
  • solve(уравнение, x) — список точных корней, включая комплексные;
  • Poly, roots, real_roots — для многочленов;
  • solve([ур1, ур2], [x, y], dict=True) — системы, ответ — список словарей.