Символы и выражения
SymPy — библиотека символьной математики. Обычный Python считает с числами: 2 ** 0.5 — это 1.4142135623730951, приближение. SymPy работает с формулами, как человек на бумаге: √ 2 остаётся корнем из двух, (x + 1)2 можно раскрыть, продифференцировать или решить уравнение — и получить точный ответ.
Символы
Переменные-буквы создают функцией symbols:
from sympy import symbols
x, y = symbols("x y")
e = (x + y) ** 2 - 2 * x * y
print(e) # -2*x*y + (x + y)**2
e — не число, а выражение: дерево из символов и операций. SymPy сразу делает только очевидные упрощения (складывает числа, объединяет одинаковые слагаемые), а остальное — по вашей команде.
Точные числа
Деление целых чисел в Python даёт дробное число с погрешностью. В SymPy для дробей есть Rational:
from sympy import Rational, sqrt
print(Rational(1, 3) + Rational(1, 6)) # 1/2
print(Rational("3/4") * 2) # 3/2
print(sqrt(8)) # 2*sqrt(2)
Осторожно: в выражении x / 3 всё в порядке (символ делится на целое — дробь точная), но x + 1 / 3 сначала посчитает 1 / 3 как обычное число 0.333…. Пишите x + Rational(1, 3).
Приближённое значение точного выражения даёт .evalf() или функция N: sqrt(2).evalf() → 1.41421356237310, N(sqrt(2), 30) — 30 знаков.
Строка → выражение: sympify
Формулу из ввода превращает в выражение функция sympify. Символы создаются автоматически:
from sympy import sympify
e = sympify("x**2 - 3*x + 2")
print(e.free_symbols) # {x}
Строка записывается по правилам Python: степень — **, умножение — явная *. Целые числа внутри sympify становятся точными, поэтому sympify("1/3") — это дробь 1/3.
Преобразования
from sympy import expand, factor, simplify, symbols
x = symbols("x")
print(expand((x + 1) ** 3)) # x**3 + 3*x**2 + 3*x + 1
print(factor(x ** 2 - 5 * x + 6)) # (x - 3)*(x - 2)
print(simplify((x ** 2 - 1) / (x - 1))) # x + 1
expand— раскрыть скобки;factor— разложить многочлен на множители (с рациональными коэффициентами);simplify— попытаться упростить «как получится»: удобно, но результат не всегда предсказуем. Если нужна конкретная форма, вызывайте конкретную функцию.
SymPy печатает выражения в своём порядке слагаемых и множителей — он одинаков для одинаковых выражений, поэтому результат expand или factor можно сравнивать как строку.
Подстановка: subs
e = x ** 2 + y
print(e.subs(x, 3)) # y + 9
print(e.subs({x: Rational(1, 2), y: 1})) # 5/4
subs возвращает новое выражение, исходное не меняется. Если подставить точные числа — получится точный ответ.
Красиво, «в столбик», выражение печатает pprint(e), а latex(e) возвращает запись для LaTeX.
Итог
symbols("x y")— символы; выражения из них — формулы, а не числа;Rational(p, q)— точная дробь;.evalf()— приближённое значение;sympify(строка)— выражение из текста;expand,factor,simplify— раскрыть, разложить, упростить;e.subs({x: значение})— подстановка.