Уравнения
Решение уравнений — одна из главных возможностей 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)— системы, ответ — список словарей.