Universidad Central del Ecuador · Facultad de Ciencias Económicas · Carrera de Estadística

Asignatura: Programación

1 Introducción

El álgebra amplía la aritmética al sustituir números concretos por símbolos que representan cantidades desconocidas o variables. Gracias a esa generalización es posible expresar relaciones entre magnitudes y razonar sobre ellas antes de conocer sus valores particulares (Baldor, 2007). La herramienta central de este razonamiento es la ecuación: una igualdad que solo se cumple para ciertos valores de la incógnita, cuya búsqueda constituye el problema de resolverla.

Entre los distintos tipos de ecuaciones, dos ocupan un lugar privilegiado en la formación universitaria. Las ecuaciones de segundo grado describen fenómenos en los que una magnitud crece y luego decrece, o viceversa, como la trayectoria de un proyectil, el área de una figura en función de uno de sus lados o el ingreso de una empresa cuando el precio afecta a la cantidad vendida (Stewart et al., 2012). Los sistemas de ecuaciones lineales, por su parte, aparecen cuando varias condiciones deben cumplirse al mismo tiempo: mezclas, repartos de recursos o equilibrios de mercado (Grossman y Flores Godoy, 2012). Desde la perspectiva estadística su importancia es aún mayor, porque el ajuste de una recta de regresión por mínimos cuadrados se reduce, precisamente, a resolver un sistema de ecuaciones lineales.

Resolver estos problemas a mano es indispensable para comprender su lógica; sin embargo, cuando los coeficientes son decimales, cuando hay muchas ecuaciones o cuando se requiere verificar resultados, la programación se vuelve una aliada natural. R es un lenguaje y entorno libre para computación estadística y gráficos (R Core Team, 2024) que incorpora aritmética de números complejos, álgebra matricial y funciones gráficas de alta calidad, a las que se suma el paquete ggplot2 (Wickham, 2016). Además, R Markdown permite reunir en un solo documento el texto explicativo, el código y sus resultados, lo que garantiza que cada cifra presentada provenga de una ejecución real y pueda reproducirse (Xie, 2015; Xie et al., 2018).

El objetivo general de esta publicación es explicar la resolución de ecuaciones de segundo grado y de sistemas de ecuaciones lineales de dos incógnitas, de modo que el lector pueda resolverlos manualmente y, después, comprobar y automatizar sus soluciones con R.

Para cumplir ese objetivo, el desarrollo se organiza en dos bloques. El primero presenta los fundamentos de las ecuaciones de segundo grado, el papel del discriminante y su resolución en R, y luego resuelve tres ejercicios que cubren los tres casos posibles del discriminante. El segundo bloque aborda los sistemas de dos ecuaciones con dos incógnitas, sus métodos de resolución y su representación matricial, y resuelve un sistema con solución única, uno sin solución y otro con infinitas soluciones. Cada ejercicio sigue la misma secuencia: planteamiento, procedimiento matemático, código en R, resultado de la ejecución e interpretación. El documento concluye con aplicaciones prácticas que muestran las ventajas de combinar el álgebra con la programación.

2 Desarrollo

Antes de empezar, se cargan los paquetes que se utilizarán a lo largo del documento. ggplot2 construye los gráficos, mientras que knitr y kableExtra dan formato a las tablas. La función tabla_formato() reúne en una sola instrucción el formato que comparten todas las tablas del documento.

library(ggplot2)     # gráficos de parábolas y rectas
library(knitr)       # función kable() para tablas
library(kableExtra)  # estilo de las tablas en el PDF

# Da formato uniforme a las tablas: en el PDF se fijan la posición y el ancho
tabla_formato <- function(datos, titulo) {
  tabla <- kable(datos, caption = titulo, booktabs = TRUE)
  if (knitr::is_latex_output()) {
    tabla <- kable_styling(tabla,
                           latex_options = c("hold_position", "scale_down"))
  }
  tabla
}

2.1 Fundamentos teóricos de las ecuaciones de segundo grado

2.1.1 Definición y forma general

Una ecuación de segundo grado, o ecuación cuadrática, con una incógnita es toda igualdad que puede escribirse en la forma general

\[ ax^2 + bx + c = 0, \qquad a \neq 0, \]

donde \(x\) es la incógnita y \(a\), \(b\) y \(c\) son números reales llamados coeficientes (Baldor, 2007). La condición \(a \neq 0\) es esencial: si \(a\) fuera cero, desaparecería el término cuadrático y la ecuación sería de primer grado.

Cada coeficiente cumple una función precisa. El coeficiente cuadrático \(a\) determina la forma de la parábola \(y = ax^2 + bx + c\): si es positivo, la parábola se abre hacia arriba; si es negativo, hacia abajo; y cuanto mayor es su valor absoluto, más cerrada resulta. El coeficiente lineal \(b\), junto con \(a\), fija la posición del eje de simetría, que es la recta \(x = -b/(2a)\). Finalmente, el término independiente \(c\) indica el punto donde la parábola corta al eje vertical, \((0, c)\).

Esta lectura gráfica es la clave de todo el tema: resolver \(ax^2 + bx + c = 0\) equivale a encontrar los valores de \(x\) en los que la parábola corta al eje \(X\), porque en esos puntos la altura \(y\) vale cero (Stewart et al., 2012).

2.1.2 La fórmula general y el discriminante

La fórmula general se obtiene completando el cuadrado. Se divide la ecuación entre \(a\), se traslada el término independiente y se suma a ambos lados el cuadrado de la mitad del coeficiente de \(x\):

\[ \begin{aligned} x^2 + \frac{b}{a}x &= -\frac{c}{a} \\ x^2 + \frac{b}{a}x + \frac{b^2}{4a^2} &= \frac{b^2}{4a^2} - \frac{c}{a} \\ \left(x + \frac{b}{2a}\right)^2 &= \frac{b^2 - 4ac}{4a^2} \\ x &= \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}. \end{aligned} \]

La cantidad que aparece bajo la raíz recibe el nombre de discriminante y se denota con la letra griega delta:

\[ \Delta = b^2 - 4ac. \]

Su nombre es preciso, ya que discrimina el tipo de soluciones antes de calcularlas. Como se resume en la Tabla 1, su signo decide si la raíz cuadrada produce dos valores reales distintos, un único valor o números complejos.

Tabla 1: Casos del discriminante y su interpretación
Signo del discriminante Tipo de soluciones Interpretación gráfica
Positivo (mayor que 0) Dos soluciones reales diferentes La parábola corta al eje X en dos puntos
Igual a 0 Una solución real doble La parábola toca al eje X en su vértice
Negativo (menor que 0) Dos soluciones complejas conjugadas La parábola no corta al eje X

Cuando el discriminante es negativo, la raíz cuadrada se calcula en el conjunto de los números complejos mediante la unidad imaginaria \(i = \sqrt{-1}\). Las dos soluciones resultan conjugadas, es decir, tienen la misma parte real y partes imaginarias opuestas: \(p + qi\) y \(p - qi\).

2.1.3 Métodos de resolución

La fórmula general resuelve cualquier ecuación cuadrática y por ello es el método de referencia. La factorización es más rápida cuando las raíces son números racionales sencillos. Se apoya en que, si \(x_1\) y \(x_2\) son las soluciones, el polinomio puede escribirse como

\[ ax^2 + bx + c = a(x - x_1)(x - x_2), \]

de modo que, al igualar a cero, basta con anular cada factor. De esta misma identidad se desprenden las relaciones de Cardano-Vieta, \(x_1 + x_2 = -b/a\) y \(x_1 x_2 = c/a\), que constituyen una forma rápida de verificar cualquier resultado.

2.1.4 Resolución de ecuaciones de segundo grado en R

R no exige una instrucción especial para resolver estas ecuaciones: basta con traducir la fórmula general a código y decidir, mediante condicionales, cuál de los tres casos se presenta. El bloque siguiente define una función propia, resolver_cuadratica(), que valida el coeficiente \(a\), calcula el discriminante y aplica la fórmula correspondiente. La función as.complex() es la pieza que permite obtener raíces complejas, ya que sqrt() aplicada a un número real negativo devuelve NaN.

# Resuelve a*x^2 + b*x + c = 0 y devuelve una lista con los resultados
resolver_cuadratica <- function(a, b, c, tolerancia = 1e-12) {
  # Validación: sin término cuadrático la ecuación no es de segundo grado
  if (abs(a) < tolerancia) {
    stop("El coeficiente a no puede ser cero.")
  }

  discriminante <- b^2 - 4 * a * c

  if (discriminante > tolerancia) {
    # Caso 1: dos soluciones reales diferentes
    x1 <- (-b + sqrt(discriminante)) / (2 * a)
    x2 <- (-b - sqrt(discriminante)) / (2 * a)
    raices <- c(x1, x2)
    tipo <- "Dos soluciones reales diferentes"
  } else if (abs(discriminante) <= tolerancia) {
    # Caso 2: una solución real doble
    raices <- -b / (2 * a)
    tipo <- "Una solución real doble"
  } else {
    # Caso 3: la raíz del discriminante se calcula como número complejo
    raiz_compleja <- sqrt(as.complex(discriminante))
    raices <- c((-b + raiz_compleja) / (2 * a),
                (-b - raiz_compleja) / (2 * a))
    tipo <- "Dos soluciones complejas conjugadas"
  }

  list(a = a, b = b, c = c,
       discriminante = discriminante,
       tipo = tipo,
       raices = raices)
}

La tolerancia evita que errores mínimos de redondeo, propios de la aritmética de punto flotante, hagan que un discriminante teóricamente nulo se interprete como positivo o negativo.

El segundo bloque define dos funciones auxiliares. mostrar_solucion() presenta los resultados de forma legible, y verificar_raices() sustituye cada raíz en el polinomio para confirmar que el resultado es cero. Además, se emplea polyroot(), función nativa de R que calcula las raíces de cualquier polinomio a partir de sus coeficientes ordenados de menor a mayor grado, como segunda comprobación independiente.

# Imprime los resultados de resolver_cuadratica() de forma ordenada
mostrar_solucion <- function(resultado) {
  cat("Ecuación:", resultado$a, "x^2 +", resultado$b, "x +",
      resultado$c, "= 0\n")
  cat("Discriminante:", resultado$discriminante, "\n")
  cat("Tipo de solución:", resultado$tipo, "\n")
  cat("Raíces:", format(resultado$raices), "\n")
}

# Sustituye las raíces en el polinomio: el resultado debe ser cero
verificar_raices <- function(resultado) {
  x <- resultado$raices
  valores <- resultado$a * x^2 + resultado$b * x + resultado$c
  round(valores, 10)  # se redondea para eliminar residuos de cómputo
}

Por último, la función graficar_parabola() dibuja la parábola asociada a cada ecuación, marca el vértice y, cuando existen, los puntos de corte con el eje \(X\).

graficar_parabola <- function(resultado, titulo) {
  a <- resultado$a; b <- resultado$b; c <- resultado$c
  h <- -b / (2 * a)              # abscisa del vértice
  k <- a * h^2 + b * h + c       # ordenada del vértice

  # Amplitud del eje X: incluye las raíces reales con un margen
  if (is.complex(resultado$raices)) {
    semiancho <- 3
  } else {
    semiancho <- max(abs(resultado$raices - h)) + 1.5
  }

  curva <- data.frame(x = seq(h - semiancho, h + semiancho,
                              length.out = 400))
  curva$y <- a * curva$x^2 + b * curva$x + c

  # Puntos destacados: vértice y, si son reales, las raíces
  puntos <- data.frame(x = h, y = k, tipo = "Vértice")
  if (!is.complex(resultado$raices)) {
    puntos <- rbind(puntos,
                    data.frame(x = resultado$raices, y = 0,
                               tipo = "Corte con el eje X"))
  }

  ggplot(curva, aes(x, y)) +
    geom_hline(yintercept = 0, colour = "grey40") +
    geom_vline(xintercept = h, linetype = "dotted", colour = "grey50") +
    geom_line(colour = "#1f5f8b", linewidth = 1) +
    geom_point(data = puntos, aes(colour = tipo), size = 3) +
    geom_text(data = puntos,
              aes(label = paste0("(", round(x, 3), "; ", round(y, 3), ")")),
              vjust = -1, size = 3.3) +
    scale_colour_manual(values = c("Vértice" = "#e69f00",
                                   "Corte con el eje X" = "#c0392b")) +
    labs(title = titulo,
         subtitle = paste("Discriminante =", resultado$discriminante),
         x = "x", y = "y", colour = NULL) +
    theme_minimal(base_size = 11) +
    theme(legend.position = "bottom")
}

2.2 Ejercicios resueltos de ecuaciones de segundo grado

2.2.1 Ejercicio 1: discriminante positivo

Planteamiento. Resolver la ecuación \(2x^2 - 7x + 3 = 0\).

Procedimiento matemático. Se identifican los coeficientes \(a = 2\), \(b = -7\) y \(c = 3\), y se calcula el discriminante:

\[ \Delta = (-7)^2 - 4(2)(3) = 49 - 24 = 25 > 0. \]

Como el discriminante es positivo, la ecuación tiene dos soluciones reales diferentes. Al aplicar la fórmula general:

\[ x = \frac{-(-7) \pm \sqrt{25}}{2(2)} = \frac{7 \pm 5}{4} \quad \Longrightarrow \quad x_1 = \frac{12}{4} = 3, \qquad x_2 = \frac{2}{4} = \frac{1}{2}. \]

Por tratarse de raíces racionales, la ecuación también puede resolverse por factorización: \(2x^2 - 7x + 3 = (2x - 1)(x - 3) = 0\), de donde \(x = 1/2\) o \(x = 3\). Las relaciones de Cardano-Vieta confirman el resultado: \(3 + 1/2 = 7/2 = -b/a\) y \(3 \cdot 1/2 = 3/2 = c/a\).

Código en R. Se resuelve la ecuación con la función propia y se compara con polyroot().

ec1 <- resolver_cuadratica(a = 2, b = -7, c = 3)
mostrar_solucion(ec1)
#> Ecuación: 2 x^2 + -7 x + 3 = 0
#> Discriminante: 25 
#> Tipo de solución: Dos soluciones reales diferentes 
#> Raíces: 3.0 0.5
# Comprobación 1: al sustituir las raíces el polinomio debe valer cero
verificar_raices(ec1)
#> [1] 0 0
# Comprobación 2: polyroot() recibe los coeficientes en orden c, b, a
round(polyroot(c(3, -7, 2)), 10)
#> [1] 0.5+0i 3.0+0i

Resultado e interpretación. R confirma un discriminante igual a 25 y las raíces \(x_1 = 3\) y \(x_2 = 0.5\), idénticas a las obtenidas manualmente. La sustitución devuelve ceros y polyroot() reproduce las mismas raíces; su parte imaginaria nula indica que son reales. La Figura 1 muestra que la parábola, abierta hacia arriba porque \(a > 0\), corta al eje \(X\) exactamente en esos dos puntos.

graficar_parabola(ec1, "Ejercicio 1: discriminante positivo")
Parábola de $y = 2x^2 - 7x + 3$ con dos cortes en el eje X.

Figura 1: Parábola de \(y = 2x^2 - 7x + 3\) con dos cortes en el eje X.

La figura evidencia la relación entre el álgebra y la geometría: el discriminante positivo se traduce en dos intersecciones con el eje horizontal, ubicadas simétricamente respecto de la recta \(x = 7/4\), que contiene al vértice.

2.2.2 Ejercicio 2: discriminante igual a cero

Planteamiento. Resolver la ecuación \(4x^2 - 12x + 9 = 0\).

Procedimiento matemático. Con \(a = 4\), \(b = -12\) y \(c = 9\), el discriminante es

\[ \Delta = (-12)^2 - 4(4)(9) = 144 - 144 = 0. \]

El discriminante nulo anula la raíz de la fórmula general, por lo que ambas soluciones coinciden:

\[ x = \frac{-(-12) \pm \sqrt{0}}{2(4)} = \frac{12}{8} = \frac{3}{2}. \]

El resultado se confirma por factorización, ya que el polinomio es un trinomio cuadrado perfecto: \(4x^2 - 12x + 9 = (2x - 3)^2 = 0\), de donde \(x = 3/2\) con multiplicidad dos.

Código en R.

ec2 <- resolver_cuadratica(a = 4, b = -12, c = 9)
mostrar_solucion(ec2)
#> Ecuación: 4 x^2 + -12 x + 9 = 0
#> Discriminante: 0 
#> Tipo de solución: Una solución real doble 
#> Raíces: 1.5
verificar_raices(ec2)
#> [1] 0
round(polyroot(c(9, -12, 4)), 10)
#> [1] 1.5+0i 1.5+0i

Resultado e interpretación. La función identifica el caso de solución real doble y devuelve \(x = 1.5\). polyroot() entrega dos veces el mismo valor, lo que refleja la multiplicidad dos de la raíz. Como se observa en la Figura 2, la parábola apenas toca al eje \(X\) en su vértice, el punto \((1.5;\, 0)\).

graficar_parabola(ec2, "Ejercicio 2: discriminante igual a cero")
Parábola de $y = 4x^2 - 12x + 9$, tangente al eje X en su vértice.

Figura 2: Parábola de \(y = 4x^2 - 12x + 9\), tangente al eje X en su vértice.

En este caso el vértice y la raíz coinciden. Geométricamente, la solución doble corresponde a la situación límite entre cortar al eje dos veces y no cortarlo.

2.2.3 Ejercicio 3: discriminante negativo

Planteamiento. Resolver la ecuación \(x^2 + 2x + 5 = 0\).

Procedimiento matemático. Con \(a = 1\), \(b = 2\) y \(c = 5\):

\[ \Delta = 2^2 - 4(1)(5) = 4 - 20 = -16 < 0. \]

Al ser negativo el discriminante, no existen soluciones reales. En el conjunto de los números complejos, \(\sqrt{-16} = 4i\), y la fórmula general da

\[ x = \frac{-2 \pm 4i}{2(1)} = -1 \pm 2i \quad \Longrightarrow \quad x_1 = -1 + 2i, \qquad x_2 = -1 - 2i. \]

La ecuación no puede factorizarse con coeficientes reales, pero sí reescribirse como \((x + 1)^2 + 4 = 0\). Esta forma muestra que el lado izquierdo es siempre mayor o igual que 4 para cualquier \(x\) real, de modo que nunca se anula.

Código en R.

ec3 <- resolver_cuadratica(a = 1, b = 2, c = 5)
mostrar_solucion(ec3)
#> Ecuación: 1 x^2 + 2 x + 5 = 0
#> Discriminante: -16 
#> Tipo de solución: Dos soluciones complejas conjugadas 
#> Raíces: -1+2i -1-2i
verificar_raices(ec3)
#> [1] 0+0i 0+0i
round(polyroot(c(5, 2, 1)), 10)
#> [1] -1+2i -1-2i
# Partes real e imaginaria de las raíces
data.frame(raiz = c("x1", "x2"),
           parte_real = Re(ec3$raices),
           parte_imaginaria = Im(ec3$raices))
#>   raiz parte_real parte_imaginaria
#> 1   x1         -1                2
#> 2   x2         -1               -2

Resultado e interpretación. R devuelve las raíces \(-1 + 2i\) y \(-1 - 2i\): comparten la parte real \(-1\) y tienen partes imaginarias opuestas, como corresponde a un par conjugado. La sustitución produce cero también en aritmética compleja. La Figura 3 muestra la parábola completamente por encima del eje \(X\), con vértice en \((-1;\, 4)\), por lo que no existe ningún corte.

graficar_parabola(ec3, "Ejercicio 3: discriminante negativo")
Parábola de $y = x^2 + 2x + 5$, sin cortes con el eje X.

Figura 3: Parábola de \(y = x^2 + 2x + 5\), sin cortes con el eje X.

Este ejercicio aclara un error frecuente: que la parábola no corte al eje \(X\) no significa que la ecuación carezca de solución, sino que sus soluciones no son números reales. La parte real de las raíces, \(-1\), coincide con la abscisa del vértice.

La Tabla 2 reúne los tres ejercicios y permite comparar cómo el discriminante anticipa el tipo de solución.

# Tabla resumen construida a partir de los objetos calculados
resumen <- data.frame(
  "Ecuación" = c("2x² - 7x + 3 = 0", "4x² - 12x + 9 = 0",
               "x² + 2x + 5 = 0"),
  Discriminante = c(ec1$discriminante, ec2$discriminante,
                    ec3$discriminante),
  Tipo = c(ec1$tipo, ec2$tipo, ec3$tipo),
  "Raíces" = c(paste(format(ec1$raices), collapse = " ; "),
             paste(format(ec2$raices), collapse = " ; "),
             paste(format(ec3$raices), collapse = " ; ")),
  check.names = FALSE
)
tabla_formato(resumen, "Resumen de las ecuaciones de segundo grado resueltas")
Tabla 2: Resumen de las ecuaciones de segundo grado resueltas
Ecuación Discriminante Tipo Raíces
2x² - 7x + 3 = 0 25 Dos soluciones reales diferentes 3.0 ; 0.5
4x² - 12x + 9 = 0 0 Una solución real doble 1.5
x² + 2x + 5 = 0 -16 Dos soluciones complejas conjugadas -1+2i ; -1-2i

2.3 Fundamentos teóricos de los sistemas de ecuaciones de dos incógnitas

2.3.1 Definición y forma general

Un sistema de ecuaciones lineales de dos incógnitas es un conjunto de dos ecuaciones de primer grado que deben satisfacerse simultáneamente. Su forma general es

\[ \begin{cases} a_1x + b_1y = c_1 \\ a_2x + b_2y = c_2 \end{cases} \]

donde \(x\) e \(y\) son las incógnitas, es decir, las cantidades desconocidas que se buscan; \(a_1, b_1, a_2, b_2\) son los coeficientes que multiplican a cada incógnita; y \(c_1, c_2\) son los términos independientes. Resolver el sistema consiste en encontrar todos los pares \((x, y)\) que cumplen ambas ecuaciones a la vez (Grossman y Flores Godoy, 2012).

Cada ecuación lineal representa una recta en el plano, de manera que la solución del sistema corresponde a los puntos comunes a las dos rectas. Solo caben tres posiciones relativas: las rectas se cortan en un punto, son paralelas o son coincidentes. Estas posiciones originan los tres tipos de sistemas que se estudian en esta sección.

2.3.2 Métodos de resolución

Los métodos algebraicos clásicos persiguen un mismo fin: eliminar una incógnita para obtener una ecuación con una sola variable (Baldor, 2007).

  • Sustitución: se despeja una incógnita en una ecuación y su expresión se reemplaza en la otra.
  • Igualación: se despeja la misma incógnita en ambas ecuaciones y se igualan las dos expresiones obtenidas.
  • Reducción: se multiplican las ecuaciones por números convenientes para que, al sumarlas o restarlas, una incógnita desaparezca.
  • Método matricial: el sistema se escribe como un producto de matrices y se resuelve con las herramientas del álgebra lineal.

2.3.3 Representación matricial

El sistema puede escribirse de forma compacta como \(AX = B\):

\[ \underbrace{\begin{pmatrix} a_1 & b_1 \\ a_2 & b_2 \end{pmatrix}}_{A} \underbrace{\begin{pmatrix} x \\ y \end{pmatrix}}_{X} = \underbrace{\begin{pmatrix} c_1 \\ c_2 \end{pmatrix}}_{B}, \]

donde \(A\) es la matriz de coeficientes, \(X\) el vector de incógnitas y \(B\) el vector de términos independientes. Si el determinante \(\det(A) = a_1b_2 - a_2b_1\) es distinto de cero, la matriz \(A\) es invertible y la solución única es \(X = A^{-1}B\). De forma equivalente, la regla de Cramer expresa la solución como cociente de determinantes:

\[ x = \frac{\begin{vmatrix} c_1 & b_1 \\ c_2 & b_2 \end{vmatrix}}{\det(A)}, \qquad y = \frac{\begin{vmatrix} a_1 & c_1 \\ a_2 & c_2 \end{vmatrix}}{\det(A)}. \]

Cuando \(\det(A) = 0\), la inversa no existe y es necesario un criterio más general. El teorema de Rouché-Frobenius compara el rango de la matriz de coeficientes \(A\) con el de la matriz ampliada \((A \mid B)\), que se obtiene al añadir a \(A\) la columna de términos independientes (Grossman y Flores Godoy, 2012). La Tabla 3 resume la clasificación resultante para dos incógnitas.

Tabla 3: Clasificación de sistemas de dos incógnitas según el teorema de Rouché-Frobenius
Condición sobre los rangos Tipo de sistema Soluciones Posición de las rectas
rango(A) = rango(A|B) = 2 Compatible determinado Una única solución Se cortan en un punto
rango(A) = rango(A|B) = 1 Compatible indeterminado Infinitas soluciones Coincidentes
rango(A) < rango(A|B) Incompatible Ninguna solución Paralelas

2.3.4 Resolución de sistemas en R

R trabaja de forma nativa con matrices. La función matrix() construye la matriz de coeficientes, det() calcula su determinante, cbind() forma la matriz ampliada y qr() permite obtener el rango de una matriz mediante su descomposición QR. La función solve(A, b) resuelve directamente el sistema, pero tiene una limitación importante: solo funciona cuando la matriz es invertible. Si el sistema no tiene solución o tiene infinitas, solve() se detiene con un error y, además, no distingue entre ambos casos.

Por esa razón, la función resolver_sistema() aplica primero el teorema de Rouché-Frobenius y solo recurre a solve() cuando ha comprobado que la solución es única. Para los sistemas indeterminados, delega en solucion_parametrica(), que expresa el conjunto infinito de soluciones en función de un parámetro.

# Expresa las infinitas soluciones de un sistema 2x2 de rango 1
solucion_parametrica <- function(A, b) {
  # Se toma la primera ecuación que no sea nula (0x + 0y)
  fila <- which(rowSums(abs(A)) > 0)[1]
  a_i <- A[fila, 1]; b_i <- A[fila, 2]; c_i <- b[fila]

  if (b_i != 0) {
    # Se despeja y: y = pendiente * x + ordenada, con x = t libre
    pendiente <- -a_i / b_i
    ordenada <- c_i / b_i
    signo <- ifelse(ordenada >= 0, " + ", " - ")
    expresion <- paste0("x = t,  y = ", round(pendiente, 4), "t",
                        signo, round(abs(ordenada), 4))
    generar <- function(t) data.frame(x = t, y = pendiente * t + ordenada)
  } else {
    # Recta vertical: x queda fija y la incógnita libre es y
    valor_x <- c_i / a_i
    expresion <- paste0("x = ", round(valor_x, 4), ",  y = t")
    generar <- function(t) data.frame(x = valor_x, y = t)
  }
  list(expresion = expresion, generar = generar)
}

# Clasifica y resuelve un sistema lineal de dos ecuaciones y dos incógnitas
resolver_sistema <- function(A, b, tolerancia = 1e-10) {
  matriz_ampliada <- cbind(A, b)                         # (A | B)
  rango_A <- qr(A, tol = tolerancia)$rank
  rango_ampliada <- qr(matriz_ampliada, tol = tolerancia)$rank
  determinante <- det(A)

  if (rango_A < rango_ampliada) {
    tipo <- "Incompatible (sin solución)"
    solucion <- NULL
  } else if (rango_A == ncol(A)) {
    tipo <- "Compatible determinado (solución única)"
    solucion <- solve(A, b)        # solo se usa si A es invertible
    names(solucion) <- c("x", "y")
  } else {
    tipo <- "Compatible indeterminado (infinitas soluciones)"
    solucion <- solucion_parametrica(A, b)
  }

  list(A = A, b = b, determinante = determinante,
       rango_A = rango_A, rango_ampliada = rango_ampliada,
       tipo = tipo, solucion = solucion)
}

# Presenta los resultados del análisis de forma legible
mostrar_sistema <- function(resultado) {
  cat("Determinante de A:", round(resultado$determinante, 10), "\n")
  cat("Rango de A:", resultado$rango_A,
      "| Rango de (A|B):", resultado$rango_ampliada, "\n")
  cat("Clasificación:", resultado$tipo, "\n")
  if (is.null(resultado$solucion)) {
    cat("Solución: el sistema no tiene solución\n")
  } else if (is.numeric(resultado$solucion)) {
    cat("Solución: x =", resultado$solucion["x"],
        " y =", resultado$solucion["y"], "\n")
  } else {
    cat("Solución general:", resultado$solucion$expresion,
        " (t es cualquier número real)\n")
  }
}

La función graficar_rectas() representa las dos ecuaciones del sistema. La segunda recta se dibuja con línea discontinua y más delgada, de modo que, si ambas coinciden, sigue siendo posible distinguirlas. Cuando la solución es única, se marca el punto de intersección.

graficar_rectas <- function(resultado, titulo, rango_x = c(-2, 6)) {
  A <- resultado$A; b <- resultado$b
  valores_x <- seq(rango_x[1], rango_x[2], length.out = 200)

  # Puntos de cada recta: se despeja y cuando su coeficiente no es cero
  rectas <- do.call(rbind, lapply(1:2, function(i) {
    if (A[i, 2] != 0) {
      data.frame(x = valores_x,
                 y = (b[i] - A[i, 1] * valores_x) / A[i, 2],
                 ecuacion = paste("Ecuación", i))
    } else {
      data.frame(x = b[i] / A[i, 1], y = valores_x,
                 ecuacion = paste("Ecuación", i))
    }
  }))

  grafico <- ggplot(rectas, aes(x, y, colour = ecuacion,
                                linetype = ecuacion, linewidth = ecuacion)) +
    geom_hline(yintercept = 0, colour = "grey70") +
    geom_vline(xintercept = 0, colour = "grey70") +
    geom_line() +
    scale_colour_manual(values = c("#1f5f8b", "#c0392b")) +
    scale_linetype_manual(values = c("solid", "dashed")) +
    scale_linewidth_manual(values = c(2.2, 0.9)) +
    labs(title = titulo, subtitle = resultado$tipo,
         x = "x", y = "y", colour = NULL, linetype = NULL,
         linewidth = NULL) +
    theme_minimal(base_size = 11) +
    theme(legend.position = "bottom")

  # Punto de intersección solo si la solución es única
  if (is.numeric(resultado$solucion)) {
    punto <- data.frame(x = resultado$solucion["x"],
                        y = resultado$solucion["y"])
    grafico <- grafico +
      geom_point(data = punto, aes(x, y), inherit.aes = FALSE,
                 size = 3.5, colour = "black") +
      geom_label(data = punto, inherit.aes = FALSE,
                 aes(x, y, label = paste0("(", x, "; ", y, ")")),
                 vjust = -0.6, size = 3.5)
  }
  grafico
}

2.4 Ejercicios resueltos de sistemas de ecuaciones

2.4.1 Ejercicio 1: sistema compatible determinado

Planteamiento. Resolver el sistema

\[ \begin{cases} 2x + 3y = 12 \\ x - y = 1 \end{cases} \]

Desarrollo matemático. Este primer sistema se resuelve con los cuatro métodos para mostrar que todos conducen al mismo resultado.

Sustitución. De la segunda ecuación, \(x = 1 + y\). Al reemplazar en la primera: \(2(1 + y) + 3y = 12\), es decir, \(2 + 5y = 12\), de donde \(y = 2\) y \(x = 1 + 2 = 3\).

Igualación. Se despeja \(x\) en ambas ecuaciones: \(x = \dfrac{12 - 3y}{2}\) y \(x = 1 + y\). Al igualar, \(12 - 3y = 2 + 2y\), por lo que \(5y = 10\) y \(y = 2\); entonces \(x = 3\).

Reducción. Se multiplica la segunda ecuación por 3, \(3x - 3y = 3\), y se suma a la primera: \(5x = 15\), así que \(x = 3\); luego \(y = x - 1 = 2\).

Método matricial. La matriz de coeficientes y su determinante son

\[ A = \begin{pmatrix} 2 & 3 \\ 1 & -1 \end{pmatrix}, \qquad \det(A) = (2)(-1) - (3)(1) = -5 \neq 0. \]

Por la regla de Cramer:

\[ x = \frac{\begin{vmatrix} 12 & 3 \\ 1 & -1 \end{vmatrix}}{-5} = \frac{-12 - 3}{-5} = 3, \qquad y = \frac{\begin{vmatrix} 2 & 12 \\ 1 & 1 \end{vmatrix}}{-5} = \frac{2 - 12}{-5} = 2. \]

La comprobación en ambas ecuaciones es inmediata: \(2(3) + 3(2) = 12\) y \(3 - 2 = 1\).

Código en R. Se construyen la matriz y el vector, se aplica la función de clasificación y se verifica el resultado con la inversa de \(A\) y con el producto matricial %*%.

# Matriz de coeficientes (se llena por filas) y vector de términos independientes
A1 <- matrix(c(2,  3,
               1, -1), nrow = 2, byrow = TRUE)
b1 <- c(12, 1)

sis1 <- resolver_sistema(A1, b1)
mostrar_sistema(sis1)
#> Determinante de A: -5 
#> Rango de A: 2 | Rango de (A|B): 2 
#> Clasificación: Compatible determinado (solución única) 
#> Solución: x = 3  y = 2
# Método matricial explícito: X = A^(-1) B
inversa_A1 <- solve(A1)
inversa_A1
#>      [,1] [,2]
#> [1,]  0.2  0.6
#> [2,]  0.2 -0.4
inversa_A1 %*% b1
#>      [,1]
#> [1,]    3
#> [2,]    2
# Verificación: A %*% X debe reproducir el vector de términos independientes
A1 %*% sis1$solucion
#>      [,1]
#> [1,]   12
#> [2,]    1

Resultado e interpretación. El determinante vale \(-5\) y ambos rangos son iguales a 2, por lo que el sistema es compatible determinado. R obtiene \(x = 3\), \(y = 2\) tanto con solve(A, b) como con el producto \(A^{-1}B\), y la verificación reproduce el vector \((12, 1)\). La Figura 4 muestra que las rectas se cortan en un único punto, \((3;\, 2)\).

graficar_rectas(sis1, "Ejercicio 1: rectas secantes")
Rectas del sistema compatible determinado y su punto de intersección.

Figura 4: Rectas del sistema compatible determinado y su punto de intersección.

Las dos rectas tienen pendientes distintas, \(-2/3\) y \(1\), lo que garantiza que se crucen exactamente una vez. Esa diferencia de pendientes es la versión geométrica de un determinante distinto de cero.

2.4.2 Ejercicio 2: sistema incompatible

Planteamiento. Resolver el sistema

\[ \begin{cases} x + 2y = 4 \\ 2x + 4y = 10 \end{cases} \]

Desarrollo matemático. El determinante de la matriz de coeficientes es \(\det(A) = (1)(4) - (2)(2) = 0\), de modo que no existe solución única. Para saber si hay infinitas soluciones o ninguna, se aplica reducción: se multiplica la primera ecuación por 2 y se resta de la segunda.

\[ (2x + 4y) - (2x + 4y) = 10 - 8 \quad \Longrightarrow \quad 0 = 2. \]

La igualdad \(0 = 2\) es falsa, lo que indica que ningún par \((x, y)\) cumple ambas ecuaciones. En términos de rangos, las filas de \(A\) son proporcionales y \(\text{rango}(A) = 1\); en cambio, la matriz ampliada contiene la fila \((1, 2, 4)\) y la fila \((2, 4, 10)\), que no son proporcionales, por lo que \(\text{rango}(A \mid B) = 2\). Al despejar \(y\) se obtienen \(y = 2 - x/2\) e \(y = 2.5 - x/2\): dos rectas con la misma pendiente y distinta ordenada en el origen.

Código en R. Primero se muestra qué ocurre si se usa solve() sin ninguna comprobación previa; tryCatch() captura el error para que el documento continúe. Después se aplica la función de clasificación.

A2 <- matrix(c(1, 2,
               2, 4), nrow = 2, byrow = TRUE)
b2 <- c(4, 10)

# solve() sin comprobación previa: falla porque A no es invertible
tryCatch(solve(A2, b2), error = function(e) conditionMessage(e))
#> [1] "Lapack routine dgesv: system is exactly singular: U[2,2] = 0"
# Análisis correcto mediante rangos
sis2 <- resolver_sistema(A2, b2)
mostrar_sistema(sis2)
#> Determinante de A: 0 
#> Rango de A: 1 | Rango de (A|B): 2 
#> Clasificación: Incompatible (sin solución) 
#> Solución: el sistema no tiene solución

Resultado e interpretación. solve() emite un error de matriz singular, pero no indica si el sistema carece de solución o tiene infinitas. La función propia, en cambio, encuentra \(\text{rango}(A) = 1 < \text{rango}(A \mid B) = 2\) y clasifica el sistema como incompatible, en concordancia con la contradicción \(0 = 2\). La Figura 5 confirma que las rectas son paralelas.

graficar_rectas(sis2, "Ejercicio 2: rectas paralelas")
Rectas paralelas del sistema incompatible: no existe punto de intersección.

Figura 5: Rectas paralelas del sistema incompatible: no existe punto de intersección.

Las rectas mantienen siempre la misma distancia vertical, de 0.5 unidades, y nunca se encuentran. Por eso el sistema no tiene solución, aunque cada ecuación por separado tenga infinitas.

2.4.3 Ejercicio 3: sistema compatible indeterminado

Planteamiento. Resolver el sistema

\[ \begin{cases} 3x - y = 2 \\ 6x - 2y = 4 \end{cases} \]

Desarrollo matemático. El determinante es \(\det(A) = (3)(-2) - (-1)(6) = -6 + 6 = 0\). Al restar de la segunda ecuación el doble de la primera se obtiene

\[ (6x - 2y) - 2(3x - y) = 4 - 2(2) \quad \Longrightarrow \quad 0 = 0. \]

La identidad \(0 = 0\) es verdadera para cualquier par \((x, y)\), lo que significa que la segunda ecuación no aporta información nueva: es la primera multiplicada por 2. En este caso \(\text{rango}(A) = \text{rango}(A \mid B) = 1\), menor que el número de incógnitas. Al despejar \(y\) en la primera ecuación, la solución general es

\[ x = t, \qquad y = 3t - 2, \qquad t \in \mathbb{R}. \]

Por ejemplo, \(t = 0\) da \((0, -2)\); \(t = 1\) da \((1, 1)\); y \(t = 2\) da \((2, 4)\). Cada uno de estos pares satisface ambas ecuaciones.

Código en R. Además de clasificar el sistema, se generan varias soluciones particulares y se verifica que todas cumplan las dos ecuaciones.

A3 <- matrix(c(3, -1,
               6, -2), nrow = 2, byrow = TRUE)
b3 <- c(2, 4)

sis3 <- resolver_sistema(A3, b3)
mostrar_sistema(sis3)
#> Determinante de A: 0 
#> Rango de A: 1 | Rango de (A|B): 1 
#> Clasificación: Compatible indeterminado (infinitas soluciones) 
#> Solución general: x = t,  y = 3t - 2  (t es cualquier número real)
# Soluciones particulares para distintos valores del parámetro t
particulares <- sis3$solucion$generar(t = c(-1, 0, 1, 2, 3))

# Se evalúa el lado izquierdo de cada ecuación: debe dar 2 y 4
particulares$ecuacion_1 <- 3 * particulares$x - particulares$y
particulares$ecuacion_2 <- 6 * particulares$x - 2 * particulares$y
particulares
#>    x  y ecuacion_1 ecuacion_2
#> 1 -1 -5          2          4
#> 2  0 -2          2          4
#> 3  1  1          2          4
#> 4  2  4          2          4
#> 5  3  7          2          4

Resultado e interpretación. La función detecta rangos iguales a 1 y devuelve la solución general \(y = 3t - 2\), que coincide con la obtenida manualmente. La tabla de soluciones particulares muestra que, para cualquier valor de \(t\), la primera ecuación da 2 y la segunda da 4. La Figura 6 presenta las dos rectas superpuestas: la línea discontinua de la segunda ecuación recorre exactamente la línea gruesa de la primera, y los puntos negros corresponden a las soluciones particulares de la tabla anterior.

# Se añaden las soluciones particulares calculadas en el bloque anterior
graficar_rectas(sis3, "Ejercicio 3: rectas coincidentes", rango_x = c(-1, 3)) +
  geom_point(data = particulares, aes(x, y), inherit.aes = FALSE,
             size = 2.5, colour = "black")
Rectas coincidentes del sistema compatible indeterminado: todos sus puntos son solución.

Figura 6: Rectas coincidentes del sistema compatible indeterminado: todos sus puntos son solución.

Como ambas ecuaciones describen la misma recta, cada uno de sus infinitos puntos es una solución del sistema. Este caso muestra por qué no basta con observar que \(\det(A) = 0\): el determinante nulo descarta la solución única, pero son los rangos los que distinguen entre infinitas soluciones y ninguna.

La Tabla 4 sintetiza los resultados obtenidos por la función resolver_sistema() en los tres ejercicios.

describir_solucion <- function(resultado) {
  if (is.null(resultado$solucion)) return("No existe")
  if (is.numeric(resultado$solucion)) {
    return(paste0("x = ", resultado$solucion["x"],
                  "; y = ", resultado$solucion["y"]))
  }
  resultado$solucion$expresion
}

resumen_sistemas <- data.frame(
  Sistema = c("2x + 3y = 12;  x - y = 1",
              "x + 2y = 4;  2x + 4y = 10",
              "3x - y = 2;  6x - 2y = 4"),
  "det(A)" = round(c(sis1$determinante, sis2$determinante,
                     sis3$determinante), 10),
  "rango(A)" = c(sis1$rango_A, sis2$rango_A, sis3$rango_A),
  "rango(A|B)" = c(sis1$rango_ampliada, sis2$rango_ampliada,
                   sis3$rango_ampliada),
  "Clasificación" = c("Compatible determinado", "Incompatible",
                      "Compatible indeterminado"),
  "Solución" = c(describir_solucion(sis1), describir_solucion(sis2),
               describir_solucion(sis3)),
  check.names = FALSE
)
tabla_formato(resumen_sistemas, "Resumen de los sistemas de ecuaciones resueltos")
Tabla 4: Resumen de los sistemas de ecuaciones resueltos
Sistema det(A) rango(A) rango(A|B) Clasificación Solución
2x + 3y = 12; x - y = 1 -5 2 2 Compatible determinado x = 3; y = 2
x + 2y = 4; 2x + 4y = 10 0 1 2 Incompatible No existe
3x - y = 2; 6x - 2y = 4 0 1 1 Compatible indeterminado x = t, y = 3t - 2

2.5 Aplicaciones prácticas y ventajas de utilizar R

2.5.1 Un problema geométrico que conduce a una ecuación cuadrática

Planteamiento. Un terreno rectangular tiene un área de 40 m², y su largo mide 3 m más que su ancho. ¿Cuáles son sus dimensiones?

Si \(x\) representa el ancho, el largo es \(x + 3\) y la condición de área se expresa como \(x(x + 3) = 40\), es decir, \(x^2 + 3x - 40 = 0\). El discriminante es \(\Delta = 9 + 160 = 169\) y las raíces son \(x = (-3 \pm 13)/2\), esto es, \(x = 5\) o \(x = -8\).

terreno <- resolver_cuadratica(a = 1, b = 3, c = -40)
mostrar_solucion(terreno)
#> Ecuación: 1 x^2 + 3 x + -40 = 0
#> Discriminante: 169 
#> Tipo de solución: Dos soluciones reales diferentes 
#> Raíces:  5 -8
# Solo tiene sentido físico la raíz positiva
ancho <- max(terreno$raices)
largo <- ancho + 3
cat("Ancho:", ancho, "m | Largo:", largo, "m | Área:", ancho * largo, "m2\n")
#> Ancho: 5 m | Largo: 8 m | Área: 40 m2

Ambas raíces son matemáticamente correctas, pero solo \(x = 5\) tiene sentido en el contexto, porque una longitud no puede ser negativa. El terreno mide 5 m de ancho y 8 m de largo. Este ejemplo recuerda que el programa resuelve la ecuación, pero la interpretación sigue siendo responsabilidad de quien plantea el problema.

2.5.2 Un problema de planteamiento que conduce a un sistema

Planteamiento. Para un evento universitario se vendieron 120 entradas y se recaudaron 460 dólares. Las entradas generales costaban 5 dólares y las de estudiante, 3 dólares. ¿Cuántas se vendieron de cada tipo?

Si \(x\) es el número de entradas generales e \(y\) el de entradas de estudiante, las condiciones del problema forman el sistema \(x + y = 120\) y \(5x + 3y = 460\).

A_entradas <- matrix(c(1, 1,
                       5, 3), nrow = 2, byrow = TRUE)
b_entradas <- c(120, 460)
mostrar_sistema(resolver_sistema(A_entradas, b_entradas))
#> Determinante de A: -2 
#> Rango de A: 2 | Rango de (A|B): 2 
#> Clasificación: Compatible determinado (solución única) 
#> Solución: x = 50  y = 70

Se vendieron 50 entradas generales y 70 de estudiante. La comprobación es directa: \(50 + 70 = 120\) entradas y \(5(50) + 3(70) = 460\) dólares.

2.5.3 Automatización: resolución de varias ecuaciones a la vez

Una de las ventajas más claras de programar la solución es que el mismo procedimiento se aplica sin esfuerzo adicional a cualquier cantidad de casos. El bloque siguiente resuelve cinco ecuaciones almacenadas en una tabla de coeficientes; la función lapply() aplica resolver_cuadratica() a cada fila y los resultados se organizan en la Tabla 5.

coeficientes <- data.frame(a = c(1, 1, 3, 1, 2),
                           b = c(0, -6, 2, -1, 3),
                           c = c(-4, 9, 1, -6, 0))

# Se resuelve cada ecuación (cada fila de la tabla)
soluciones <- lapply(seq_len(nrow(coeficientes)), function(i) {
  with(coeficientes[i, ], resolver_cuadratica(a, b, c))
})

tabla_lote <- data.frame(
  a = coeficientes$a, b = coeficientes$b, c = coeficientes$c,
  Discriminante = sapply(soluciones, function(s) s$discriminante),
  Tipo = sapply(soluciones, function(s) s$tipo),
  "Raíces" = sapply(soluciones, function(s)
    paste(format(round(s$raices, 4)), collapse = " ; ")),
  check.names = FALSE
)
tabla_formato(tabla_lote,
              "Resolución automatizada de cinco ecuaciones de segundo grado")
Tabla 5: Resolución automatizada de cinco ecuaciones de segundo grado
a b c Discriminante Tipo Raíces
1 0 -4 16 Dos soluciones reales diferentes 2 ; -2
1 -6 9 0 Una solución real doble 3
3 2 1 -8 Dos soluciones complejas conjugadas -0.3333+0.4714i ; -0.3333-0.4714i
1 -1 -6 25 Dos soluciones reales diferentes 3 ; -2
2 3 0 9 Dos soluciones reales diferentes 0.0 ; -1.5

2.5.4 Conexión con la estadística: la recta de mínimos cuadrados

La regresión lineal simple ajusta una recta \(\hat{y} = \beta_0 + \beta_1 x\) a un conjunto de datos. Los coeficientes que minimizan la suma de los cuadrados de los residuos son la solución de un sistema de dos ecuaciones con dos incógnitas, conocido como sistema de ecuaciones normales:

\[ \begin{cases} n\,\beta_0 + \left(\sum x_i\right)\beta_1 = \sum y_i \\[4pt] \left(\sum x_i\right)\beta_0 + \left(\sum x_i^2\right)\beta_1 = \sum x_i y_i \end{cases} \]

Con un conjunto ilustrativo de seis observaciones (horas de estudio y calificación obtenida), el bloque siguiente construye ese sistema, lo resuelve con la misma función empleada en los ejercicios y compara el resultado con lm(), la función de R para modelos lineales.

horas <- 1:6
calificacion <- c(4.5, 5.8, 6.1, 7.4, 8.0, 9.2)   # datos ilustrativos
n <- length(horas)

# Sistema de ecuaciones normales en forma matricial
A_normal <- matrix(c(n,          sum(horas),
                     sum(horas), sum(horas^2)), nrow = 2, byrow = TRUE)
b_normal <- c(sum(calificacion), sum(horas * calificacion))

ajuste_sistema <- resolver_sistema(A_normal, b_normal)
mostrar_sistema(ajuste_sistema)
#> Determinante de A: 105 
#> Rango de A: 2 | Rango de (A|B): 2 
#> Clasificación: Compatible determinado (solución única) 
#> Solución: x = 3.693333  y = 0.8971429
# Comparación con la función lm()
coef(lm(calificacion ~ horas))
#> (Intercept)       horas 
#>   3.6933333   0.8971429

En la salida de mostrar_sistema(), la primera incógnita (rotulada x) corresponde a \(\beta_0\) y la segunda (rotulada y) a \(\beta_1\). Los coeficientes obtenidos al resolver el sistema coinciden con los que calcula lm(): la ordenada en el origen es aproximadamente 3.693 y la pendiente, 0.897. En términos del ejemplo, cada hora adicional de estudio se asocia con un aumento cercano a 0.9 puntos en la calificación. La coincidencia muestra que una de las herramientas centrales de la estadística descansa, en su forma más simple, sobre la resolución de un sistema lineal de dos incógnitas.

2.5.5 Ventajas de utilizar R

Los ejercicios anteriores permiten resumir las ventajas de incorporar R en el estudio de estos temas:

  • Verificación independiente. Cada resultado manual puede contrastarse con el cálculo del programa y con funciones nativas como polyroot() o lm(), lo que reduce los errores aritméticos.
  • Tratamiento de todos los casos. La aritmética compleja y el cálculo de rangos permiten abordar discriminantes negativos y sistemas singulares sin procedimientos especiales.
  • Automatización. Una función escrita una vez resuelve cualquier número de ecuaciones o sistemas, como se mostró en la Tabla 5.
  • Visualización. Los gráficos generados a partir de los mismos datos conectan el resultado algebraico con su significado geométrico.
  • Reproducibilidad. Al integrar texto y código en R Markdown, cada cifra del documento se recalcula al compilarlo, de modo que no hay resultados transcritos a mano (Xie et al., 2018).
  • Difusión. El mismo archivo R Markdown genera una versión HTML que puede publicarse en RPubs, el servicio gratuito de Posit para compartir documentos de este tipo (RPubs, s.f.). Posit ha anunciado que RPubs admitirá nuevas publicaciones hasta el 30 de junio de 2027 y que los documentos ya publicados seguirán disponibles hasta el 31 de diciembre de 2031 (Cheng y Wickham, 2026).

3 Conclusiones

El desarrollo de esta publicación permitió consolidar dos ideas centrales. En las ecuaciones de segundo grado, el discriminante \(\Delta = b^2 - 4ac\) anticipa el tipo de solución antes de calcularla: dos raíces reales distintas cuando es positivo, una raíz doble cuando es nulo y un par de raíces complejas conjugadas cuando es negativo. En los sistemas lineales de dos incógnitas, la comparación entre el rango de la matriz de coeficientes y el de la matriz ampliada permite distinguir con rigor entre solución única, infinitas soluciones y ausencia de solución. En ambos temas, la interpretación gráfica, sea mediante los cortes de la parábola con el eje \(X\) o mediante la posición relativa de dos rectas, dio sentido concreto a cada resultado.

Combinar el procedimiento algebraico con la programación resultó más provechoso que emplear cualquiera de los dos por separado. La resolución manual obligó a comprender cada paso, y el código permitió verificar esos pasos, extenderlos a muchos casos y detectar situaciones que una herramienta mal empleada puede ocultar. El ejemplo más claro fue el uso de solve(): aplicada sin comprobaciones previas, esta función falla ante un sistema singular sin explicar la causa, mientras que una función construida a partir de la teoría clasifica correctamente el sistema y describe su conjunto de soluciones.

Finalmente, R demostró ser una herramienta adecuada tanto para aprender como para resolver problemas matemáticos. Sus funciones matriciales, su aritmética compleja y sus capacidades gráficas cubren todos los casos estudiados, y R Markdown convierte el trabajo en un documento reproducible y fácil de compartir. La conexión con la recta de mínimos cuadrados mostró, además, que estos contenidos no se limitan a ejercicios aislados, sino que constituyen la base de métodos estadísticos de uso cotidiano.

Referencias

Baldor, A. (2007). Álgebra (2.ª ed.). Grupo Editorial Patria.

Cheng, J., y Wickham, H. (2026, 21 de julio). Migrating to Connect Cloud: Posit’s unified publishing solution. Posit. https://posit.co/blog/migrating-connect-cloud-posits-unified-publishing-solution

Grossman, S. I., y Flores Godoy, J. J. (2012). Álgebra lineal (7.ª ed.). McGraw-Hill.

R Core Team. (2024). R: A language and environment for statistical computing. R Foundation for Statistical Computing. https://www.R-project.org/

RPubs. (s.f.). Getting started with RPubs. Recuperado el 6 de noviembre de 2026, de https://rpubs.com/about/getting-started

Stewart, J., Redlin, L., y Watson, S. (2012). Precálculo: Matemáticas para el cálculo (6.ª ed.). Cengage Learning.

Wickham, H. (2016). ggplot2: Elegant graphics for data analysis (2.ª ed.). Springer-Verlag. https://ggplot2.tidyverse.org

Xie, Y. (2015). Dynamic documents with R and knitr (2.ª ed.). Chapman and Hall/CRC.

Xie, Y., Allaire, J. J., y Grolemund, G. (2018). R Markdown: The definitive guide. Chapman and Hall/CRC. https://bookdown.org/yihui/rmarkdown/