Código
import numpy as np
import sympy as sp
print("NumPy: ", np.sqrt(8)) # Aproximación decimalNumPy: 2.8284271247461903
Código
print("SymPy: ", sp.sqrt(8)) # Resultado exactoSymPy: 2*sqrt(2)
Fecha: 10 y 12 de noviembre, 2026
Invitado: Dr. José Crispin Ruiz Pantaleon (JCRP)
SymPy es una biblioteca de Python para hacer matemáticas simbólicas: manipula expresiones con variables como lo haríamos con lápiz y papel, y obtiene resultados exactos en lugar de aproximaciones decimales.
En este capítulo veremos:
import numpy as np
import sympy as sp
print("NumPy: ", np.sqrt(8)) # Aproximación decimalNumPy: 2.8284271247461903
print("SymPy: ", sp.sqrt(8)) # Resultado exactoSymPy: 2*sqrt(2)
| Cálculo numérico (NumPy) | Cálculo simbólico (SymPy) | |
|---|---|---|
| Trabaja con | Números decimales. | Símbolos y expresiones exactas. |
| \(\sqrt{8}\) | 2.8284271247461903 |
2*sqrt(2) |
| \(\frac{1}{3} + \frac{1}{6}\) | 0.5 (con posibles errores de redondeo) |
1/2 (fracción exacta) |
| Derivar \(x^2\) | Aproxima la pendiente en puntos. | Obtiene \(2x\). |
| Ideal para | Datos, simulaciones, grandes cantidades de números. | Álgebra, cálculo, demostrar y verificar fórmulas. |
print(0.1 + 0.2) # Error de redondeo de los decimales0.30000000000000004
print(sp.Rational(1, 10) + sp.Rational(2, 10)) # Fracciones exactas3/10
print(sp.pi.evalf(30)) # Pi con 30 dígitos3.14159265358979323846264338328
En tu computadora, instálalo en tu entorno virtual (consulta el apéndice Entornos para trabajar con Python):
python -m pip install sympyEn Google Colab y en los editores de esta página ya está instalado. Por convención se importa con el alias sp:
import sympy as sp
print(sp.__version__)1.14.0
En Python, una variable debe tener un valor antes de usarse. En SymPy primero declaramos qué nombres son símbolos matemáticos con sp.symbols():
x, y = sp.symbols("x y")
expresion = x**2 + 2*x*y + y**2
print(expresion)x**2 + 2*x*y + y**2
print(type(x))<class 'sympy.core.symbol.Symbol'>
Para elevar a una potencia se usa **, no ^. En Python, x^2 es otra operación (el “o exclusivo” entre bits) y produce un error con los símbolos.
Podemos indicar supuestos sobre los símbolos, que SymPy usa para simplificar:
t = sp.symbols("t")
r = sp.symbols("r", positive=True)
print(sp.sqrt(t**2)) # No sabe si t es negativosqrt(t**2)
print(sp.sqrt(r**2)) # Sabe que r es positivor
| Método | ¿Qué hace? | Ejemplo |
|---|---|---|
expr.subs(x, valor) |
Sustituye un símbolo por un valor u otra expresión. | (x**2).subs(x, 3) → 9 |
expr.evalf() o sp.N(expr) |
Calcula el valor decimal. | sp.sqrt(2).evalf() → 1.414... |
sp.N(expr, n) |
Valor decimal con n dígitos. |
sp.N(sp.pi, 50) |
f = x**2 + 3*x - 1
print(f.subs(x, 2)) # Evaluar en x = 29
print(f.subs(x, y + 1)) # Sustituir por otra expresión3*y + (y + 1)**2 + 2
print(f.subs(x, sp.sqrt(2))) # Resultado exacto1 + 3*sqrt(2)
print(f.subs(x, sp.sqrt(2)).evalf()) # Resultado decimal5.24264068711928
Si escribes 1/2 dentro de una expresión, Python calcula primero el decimal 0.5. Para obtener una fracción exacta usa sp.Rational():
print(x + 1/2) # 0.5: decimalx + 0.5
print(x + sp.Rational(1, 2)) # 1/2: fracción exactax + 1/2
| Función | ¿Qué hace? | Ejemplo | Resultado |
|---|---|---|---|
sp.expand() |
Desarrolla productos y potencias. | sp.expand((x + 1)**2) |
x**2 + 2*x + 1 |
sp.factor() |
Factoriza. | sp.factor(x**2 - 1) |
(x - 1)*(x + 1) |
sp.simplify() |
Intenta encontrar la forma más simple. | sp.simplify(sp.sin(x)**2 + sp.cos(x)**2) |
1 |
sp.cancel() |
Simplifica fracciones de polinomios. | sp.cancel((x**2 - 1)/(x - 1)) |
x + 1 |
sp.apart() |
Fracciones parciales. | sp.apart(1/(x**2 - 1)) |
-1/(2*(x + 1)) + 1/(2*(x - 1)) |
sp.collect() |
Agrupa términos por un símbolo. | sp.collect(x*y + x, x) |
x*(y + 1) |
sp.trigsimp() |
Simplifica expresiones trigonométricas. | sp.trigsimp(2*sp.sin(x)*sp.cos(x)) |
sin(2*x) |
print(sp.expand((x + y)**3))x**3 + 3*x**2*y + 3*x*y**2 + y**3
print(sp.factor(x**3 - x**2 - x + 1))(x - 1)**2*(x + 1)
print(sp.cancel((x**2 - 1) / (x - 1)))x + 1
print(sp.apart(1 / (x**2 - 1)))-1/(2*(x + 1)) + 1/(2*(x - 1))
Para escribir una ecuación no se usa = (que asigna) ni == (que compara), sino sp.Eq(lado_izquierdo, lado_derecho). Para resolverla usamos sp.solve():
ecuacion = sp.Eq(x**2 - 5*x, -6)
print(ecuacion)Eq(x**2 - 5*x, -6)
print(sp.solve(ecuacion, x))[2, 3]
Si pasamos solo una expresión, sp.solve() supone que está igualada a cero:
print(sp.solve(x**2 - 4, x))[-2, 2]
print(sp.solve(x**2 + 1, x)) # Soluciones complejas: I es la unidad imaginaria[-I, I]
Con sp.solveset() podemos indicar en qué conjunto buscar soluciones:
print(sp.solveset(x**2 + 1, x, domain=sp.S.Reals)) # Sin soluciones realesEmptySet
SymPy puede resolver la ecuación cuadrática con coeficientes simbólicos y obtener la fórmula general que usamos en el capítulo de condicionales:
a, b, c = sp.symbols("a b c")
print(sp.solve(a*x**2 + b*x + c, x))[(-b - sqrt(-4*a*c + b**2))/(2*a), (-b + sqrt(-4*a*c + b**2))/(2*a)]
Es el mismo sistema que resolvimos con np.linalg.solve() en el capítulo de NumPy, pero ahora con solución exacta:
x, y, z = sp.symbols("x y z")
sistema = [sp.Eq(2*x + y - z, 3),
sp.Eq(x - y + 2*z, 5),
sp.Eq(3*x + 2*y + z, 10)]
print(sp.solve(sistema, [x, y, z])){x: 2, y: 1, z: 2}
| Operación | Notación | SymPy |
|---|---|---|
| Límite | \(\lim_{x \to a} f(x)\) | sp.limit(f, x, a) |
| Límite al infinito | \(\lim_{x \to \infty} f(x)\) | sp.limit(f, x, sp.oo) |
| Derivada | \(\frac{df}{dx}\) | sp.diff(f, x) |
| Derivada de orden \(n\) | \(\frac{d^n f}{dx^n}\) | sp.diff(f, x, n) |
| Derivada parcial | \(\frac{\partial f}{\partial y}\) | sp.diff(f, y) |
| Integral indefinida | \(\int f\,dx\) | sp.integrate(f, x) |
| Integral definida | \(\int_a^b f\,dx\) | sp.integrate(f, (x, a, b)) |
| Serie de Taylor | \(f(x) \approx \sum \frac{f^{(n)}(a)}{n!}(x-a)^n\) | sp.series(f, x, a, n) |
| Suma | \(\sum_{i=1}^{n} f(i)\) | sp.summation(f, (i, 1, n)) |
El infinito se escribe sp.oo (dos letras “o”), y las constantes son sp.pi, sp.E y sp.I.
x, n = sp.symbols("x n")
print(sp.limit(sp.sin(x) / x, x, 0))1
print(sp.limit((1 + 1/n)**n, n, sp.oo)) # El número eE
print(sp.limit(1/x, x, 0, dir="+")) # Límite por la derechaoo
f = x**2 * sp.sin(x)
print(sp.diff(f, x)) # Primera derivadax**2*cos(x) + 2*x*sin(x)
print(sp.diff(f, x, 2)) # Segunda derivada-x**2*sin(x) + 4*x*cos(x) + 2*sin(x)
x, y = sp.symbols("x y")
g = x**2 * y + sp.sin(y)
print(sp.diff(g, y)) # Derivada parcial respecto a yx**2 + cos(y)
print(sp.integrate(x * sp.exp(x), x)) # Indefinida (sin la constante C)(x - 1)*exp(x)
print(sp.integrate(x * sp.exp(x), (x, 0, 1))) # Definida1
print(sp.integrate(sp.exp(-x**2), (x, -sp.oo, sp.oo))) # Integral de Gausssqrt(pi)
print(sp.series(sp.sin(x), x, 0, 8))x - x**3/6 + x**5/120 - x**7/5040 + O(x**8)
print(sp.series(sp.exp(x), x, 0, 5).removeO()) # Sin el término O(x^n)x**4/24 + x**3/6 + x**2/2 + x + 1
Para sumar los números del 1 al 100 podríamos sumarlos uno por uno; en el capítulo de ciclos for aprenderemos a hacerlo con un ciclo. SymPy, en cambio, obtiene directamente la fórmula para cualquier \(n\):
i, n = sp.symbols("i n", integer=True, positive=True)
print(sp.factor(sp.summation(i, (i, 1, n)))) # 1 + 2 + ... + nn*(n + 1)/2
print(sp.summation(i, (i, 1, 100))) # Con n = 1005050
sp.Matrix trabaja con valores exactos, incluidas fracciones y símbolos:
M = sp.Matrix([[2, 1],
[1, 3]])
print("det(M) =", M.det())det(M) = 5
print("M^-1 =", M.inv())M^-1 = Matrix([[3/5, -1/5], [-1/5, 2/5]])
print("Valores propios:", M.eigenvals())Valores propios: {5/2 - sqrt(5)/2: 1, sqrt(5)/2 + 5/2: 1}
| Operación | SymPy |
|---|---|
| Producto | A * B (en SymPy, * sí es el producto de matrices) |
| Transpuesta | A.T |
| Determinante | A.det() |
| Inversa | A.inv() |
| Forma escalonada reducida | A.rref() |
| Valores y vectores propios | A.eigenvals(), A.eigenvects() |
Para resolver una ecuación diferencial ordinaria declaramos una función desconocida con sp.Function() y usamos sp.dsolve(). Por ejemplo, \(y'' + y = 0\):
y = sp.Function("y")
x = sp.symbols("x")
edo = sp.Eq(y(x).diff(x, 2) + y(x), 0)
print(sp.dsolve(edo, y(x)))Eq(y(x), C1*sin(x) + C2*cos(x))
C1 y C2 son las constantes de integración.
lambdify()Para evaluar una expresión en muchos puntos (por ejemplo, para graficarla), conviértela en una función de NumPy con sp.lambdify():
expr = sp.sin(x)**2
f_numpy = sp.lambdify(x, expr, "numpy")
valores = np.linspace(0, np.pi, 5)
print(f_numpy(valores).round(4))[0. 0.5 1. 0.5 0. ]
Usaremos esta herramienta en el capítulo de visualización de datos.
sp.latex() convierte cualquier expresión al código LaTeX que usamos en Markdown y Quarto:
integral = sp.Integral(sp.exp(-x**2), (x, -sp.oo, sp.oo))
print(sp.latex(integral), "=", sp.latex(integral.doit()))\int\limits_{-\infty}^{\infty} e^{- x^{2}}\, dx = \sqrt{\pi}
En un documento de Quarto puedes mostrar el resultado como fórmula con la opción #| output: asis:
print(f"$${sp.latex(integral)} = {sp.latex(integral.doit())}$$")\[\int\limits_{-\infty}^{\infty} e^{- x^{2}}\, dx = \sqrt{\pi}\]
| Error | Ejemplo | Corrección |
|---|---|---|
| Usar un símbolo sin declararlo | sp.diff(x**2, x) sin sp.symbols (NameError) |
x = sp.symbols("x") |
Usar ^ para potencias |
x^2 (TypeError) |
x**2 |
Fracciones con / entre enteros |
x + 1/3 da x + 0.333... |
x + sp.Rational(1, 3) |
| Usar funciones de NumPy con símbolos | np.sin(x) (TypeError) |
sp.sin(x) |
Escribir ecuaciones con = |
x**2 = 4 (SyntaxError) |
sp.Eq(x**2, 4) |
Olvidar el símbolo en solve o diff |
sp.diff(x*y) (ambiguo) |
sp.diff(x*y, x) |
Resuelve los ejercicios en los editores interactivos. Recuerda que lo que escribas no se guarda al recargar la página. La primera vez que ejecutes un editor, SymPy puede tardar unos segundos en cargar.
Usa sp.expand((x + 1)**3) y sp.factor(x**2 - 5*x + 6). Recuerda que la potencia se escribe con **.
import sympy as sp
x = sp.symbols("x")
print(sp.expand((x + 1)**3)) # x**3 + 3*x**2 + 3*x + 1
sp.factor(x**2 - 5*x + 6) # (x - 3)*(x - 2)Encuentra todas las raíces del polinomio \(p(x) = x^3 - 6x^2 + 11x - 6\). Después verifica que cada raíz cumple \(p(r) = 0\) sustituyéndola con subs(). Deja la lista de raíces en la última línea.
sp.solve(p, x) regresa una lista con las raíces. Para verificar: p.subs(x, 1).
import sympy as sp
x = sp.symbols("x")
p = x**3 - 6*x**2 + 11*x - 6
raices = sp.solve(p, x)
print("Raíces:", raices) # [1, 2, 3]
print("p(1) =", p.subs(x, 1)) # 0
raicesCalcula \(\displaystyle\lim_{n \to \infty} \left(1 + \frac{1}{n}\right)^n\) y muestra su valor con 20 dígitos. Deja el límite en la última línea.
El infinito es sp.oo. Para ver el valor con 20 dígitos usa sp.N(limite, 20).
import sympy as sp
n = sp.symbols("n")
limite = sp.limit((1 + 1/n)**n, n, sp.oo)
print("Límite:", limite) # E
print("Valor decimal:", sp.N(limite, 20)) # 2.7182818284590452354
limitePara \(f(x) = x^2 \sin(x)\):
sp.diff(f, x) y sp.diff(f, x, 2). Para evaluar: primera.subs(x, sp.pi). Usa sp.pi, no 3.1416, para obtener el resultado exacto.
import sympy as sp
x = sp.symbols("x")
f = x**2 * sp.sin(x)
primera = sp.diff(f, x) # x**2*cos(x) + 2*x*sin(x)
segunda = sp.diff(f, x, 2) # -x**2*sin(x) + 4*x*cos(x) + 2*sin(x)
print("f'(x) =", primera)
print("f''(x) =", segunda)
primera.subs(x, sp.pi) # -pi**2sp.integrate(x * sp.exp(x), x) para la indefinida y sp.integrate(x * sp.exp(x), (x, 0, 1)) para la definida. Para verificar, deriva: sp.diff(indefinida, x).
import sympy as sp
x = sp.symbols("x")
indefinida = sp.integrate(x * sp.exp(x), x)
print("Integral indefinida:", indefinida) # (x - 1)*exp(x)
print("Verificación:", sp.simplify(sp.diff(indefinida, x))) # x*exp(x)
sp.integrate(x * sp.exp(x), (x, 0, 1)) # 1Usa sp.summation() para obtener una fórmula de \(\displaystyle\sum_{i=1}^{n} i^2 = 1^2 + 2^2 + \cdots + n^2\). Factoriza el resultado y déjalo en la última línea. Después úsala para calcular la suma con \(n = 100\).
sp.factor(sp.summation(i**2, (i, 1, n))). Para evaluar la fórmula: formula.subs(n, 100).
import sympy as sp
i, n = sp.symbols("i n", integer=True, positive=True)
formula = sp.factor(sp.summation(i**2, (i, 1, n)))
print("Fórmula:", formula) # n*(n + 1)*(2*n + 1)/6
print("Con n = 100:", formula.subs(n, 100)) # 338350
formulaLa serie de Leibniz permite aproximar \(\pi\); en el capítulo de ciclos for la usaremos para aproximarlo sumando 1000 de sus términos. Con SymPy podemos calcular la suma infinita de forma exacta:
sp.summation((-1)**k / (2*k + 1), (k, 0, sp.oo)) y sp.summation(1 / k**2, (k, 1, sp.oo)).
import sympy as sp
k = sp.symbols("k", integer=True)
leibniz = sp.summation((-1)**k / (2*k + 1), (k, 0, sp.oo))
print("Serie de Leibniz:", leibniz) # pi/4
basilea = sp.summation(1 / k**2, (k, 1, sp.oo))
print("Problema de Basilea:", basilea, "≈", sp.N(basilea)) # pi**2/6 ≈ 1.64493406684823
basileaPor eso, para aproximar \(\pi\) con esta serie, hay que multiplicar la suma por 4: \(4 \cdot \frac{\pi}{4} = \pi\). Lo haremos en el capítulo de ciclos for.
| Tema | SymPy |
|---|---|
| Símbolos | x, y = sp.symbols("x y") |
| Sustituir / evaluar | expr.subs(x, 2), expr.evalf(), sp.N(expr, n) |
| Fracciones y constantes | sp.Rational(1, 3), sp.pi, sp.E, sp.I, sp.oo |
| Manipular expresiones | expand, factor, simplify, cancel, apart, trigsimp |
| Ecuaciones | sp.Eq(izq, der), sp.solve(), sp.solveset() |
| Cálculo | limit, diff, integrate, series, summation |
| Matrices | sp.Matrix, .det(), .inv(), .eigenvals() |
| Ecuaciones diferenciales | sp.Function, sp.dsolve() |
| Conversión | sp.lambdify() (a NumPy), sp.latex() (a LaTeX) |