Matemáticas para programadores
Tiempo de lectura: 8.01 minutos
Lo que encontrarás en este artículo
Introducción
La gente a menudo dice que no necesitas saber matemáticas para aprender a programar.
Y eso es verdad hasta cierto punto.
Sin embargo, las tecnologías más avanzadas parecen magia, ¿no?
Pero la magia no es real. Las matemáticas lo explican todo.
Los desarrolladores a menudo evitan aprender matemáticas porque parece intimidante, pero en realidad las matemáticas hacen que conceptos avanzados como computer graphics y redes neuronales sean más fáciles de entender.
Y no solo eso, sino que también desbloquean los secretos del universo físico.
Existen conceptos matemáticos abstractos que son muy útiles para los programadores.
Así que hoy revisaremos 10 de ellos.
Entenderlos te hará pensar más como un ingeniero.
Permíteme explicarte estos 10 conceptos matemáticos importantes, usando memes y otros medios visuales para que lo comprendas fácilmente.
¿Te gusta más aprender viendo?
Si lo deseas, puedes aprender los 10 conceptos viendo el siguiente video:
Nota: Míralo completo, ya que tengo un regalo para ti, escondido, ya sea al medio o al final 🙂.
Si te gusta más aprender leyendo, o deseas complementar tu aprendizaje, continúa por aquí:
Empecemos con el punto número 1.
Álgebra Booleana
Esta se utiliza casi cada vez que escribes código.
Un booleano es una variable binaria que puede tener 2 posibles valores: verdadero o falso.
Existen 3 operadores que puedes usar para trabajar con booleanos:
- AND,
- OR,
- NOT.
También conocidos respectivamente como:
- conjunción,
- disyunción, y
- negación.
Ejemplo
Imagina que estás tratando de conseguir novia.
Podemos usar las variables booleanas: rico y guapo para describirte.
Si eres rico y guapo, definitivamente conseguirás una novia.
Pero si no eres rico y no eres guapo, tendrás que conformarte con una novia imaginaria o ChatGPT.
Si eres rico o guapo, aún puedes conseguir una novia, pero tu selección será más limitada.
Podemos representar esta lógica y código con declaraciones "if":
rico = False
guapo = False
def buscar_novia():
if rico and guapo:
return 'novia asegurada' # Ambos criterios cumplidos
elif not rico and not guapo:
return 'novia IA' # Ningún criterio cumplido
else: # Cumple al menos uno de los criterios
return 'menos opciones'
Y también podemos hacerlo visualmente con diagramas de Venn, que seguro los viste en la primaria.
Además, puedes crear tablas de verdad como esta de aquí, que son útiles cuando ocurre un apocalipsis zombie:
Eso nos lleva al concepto número 2.
Sistemas numéricos
Un sistema de numeración es un conjunto de símbolos y reglas, que determinan qué números son válidos en una base determinada.
Por ejemplo, tenemos el sistema numérico en base 2.
Base 10
A lo largo de la historia, los humanos han ideado muchas formas de contar, pero casi todas usan base 10, como los 10 dedos de tus manos.
Por ejemplo, para el número 423 en base 10:
- El 4 está en el lugar de las centenas, representando 4 veces 100.
- El 2 está en el lugar de las decenas, o 2 veces 10.
- Luego el número final se multiplica por 1.
Base 2
Las computadoras funcionan con un sistema de numeración en base 2.
En base 2, las cosas funcionan de la misma manera, pero como solo tenemos 2 símbolos disponibles, cada lugar se multiplica por 2, como 2, 4, 8, 16, 32, 64, 128, y así sucesivamente.
Una vez entiendes esto, empiezas a comprender cómo funcionan otras bases.
Base 16
La base 16 o hexadecimal, utiliza los dígitos del 0 al 9 y las letras de la A la F.
Se usa comúnmente para representar valores binarios de una manera más concisa, ya que cada dígito hexadecimal se corresponde con 4 bits.
Base 64
Y también tienes la base64, que introduce aún más letras y símbolos para codificar valores binarios, lo que permite a los desarrolladores por ejemplo, representar imágenes como una cadena de texto.
Mientras que las computadoras utilizan la base 2 detrás de escena, todavía necesitan representar números base 10 para los humanos,
Puntos flotantes
Números de punto flotante.
Adelante:
Ejecuta 0.1 más 0.2 en tu lenguaje de programación favorito.
resultado = 0.1 + 0.2
print(resultado)
El resultado debería ser 0.30000000000000004
.
¿Cómo puede una computadora cometer un error tan "tonto"?
Bueno, en la ciencia:
- Los números pueden ser muy grandes cuando se habla del espacio, y
- muy pequeños cuando se trata de cosas como átomos.
No escribimos estos números completamente:
En su lugar usamos la notación científica, donde los exponentes elevan a un valor aproximado, para simplificar y ser más concisos.
Las computadoras utilizan un enfoque similar con los números de punto flotante, porque tienen una cantidad limitada de espacio:
- Ya sea 32 bits para precisión simple, o
- 64 para precisión doble, que es la predeterminada en lenguajes como Python y JavaScript.
Se llama punto flotante porque no hay un número fijo de dígitos antes o después del punto decimal, lo que permite a los desarrolladores equilibrar entre rango y precisión.
- Algunos números, como 0.1, no pueden representarse perfectamente como un punto flotante binario.
- Esa es la razón por la que obtenemos estos pequeños errores de redondeo.
Logaritmos
Ahora que sabes cómo funcionan los números, podemos empezar a hablar sobre las funciones logarítmicas, que tal vez recuerdes de tus clases de álgebra.
Para entenderlas, piensa en un tronco de árbol.
- El tronco comienza con 16 metros,
- luego lo cortamos por la mitad una y otra vez,
- hasta llegar a una longitud de 2.
Observa cómo cuando intentamos dibujar una línea a través de él, no es perfectamente recta, sino que se curva gradualmente.
En informática, así es como funcionan muchos algoritmos, como la búsqueda binaria.
Lo interesante es que:
- Si conocemos cuántas veces cortamos el tronco,
- podemos elevar 2 a la potencia de ese valor, en este caso 4,
- y obtener la longitud original del tronco.
Eso se llama exponenciación, y los logaritmos son exactamente lo opuesto.
Imagina que:
- No conocemos el exponente,
- solo conocemos la longitud original, y
- queremos averiguar cuántas veces tendríamos que cortar el tronco para obtener una longitud de 2.
Podeamos calcular eso con un logaritmo en base 2 de la longitud original, devolviendo un valor de 4.
Cuando es base 2, se llama logaritmo binario.
Sin embargo, en matemáticas es más común usar base 10, y en ese caso se llama logaritmo común.
Esto es interesante, pero, ahora cambiemos de tema a la teoría de conjuntos.
Teoría de conjuntos
Un conjunto (o set) es tan sólo una colección desordenada de valores únicos.
El mejor ejemplo es una base de datos relacional donde cada tabla es un conjunto de filas únicas.
Estas tablas pueden unirse de diversas maneras basadas en la teoría de conjuntos (set theory).
Por ejemplo, para seleccionar registros que coincidan en ambas tablas:
- se realiza un inner join,
- que sería una intersección en la teoría de conjuntos.
O, para tomar todos los registros presentes en ambas tablas:
- se hace un full outer join,
- que es una unión en la teoría de conjuntos.
Al realizar left y right joins, estos conceptos se combinan, como al unir una intersección con la diferencia entre los 2 conjuntos.
Importante:
- Hasta este punto estamos hablando de estructuras que tienen un número finito de elementos.
- Esto cae bajo el ámbito de las matemáticas discretas.
- Tenemos también las matemáticas continuas, como la geometría y el cálculo, que tratan con números reales y aproximaciones.
Y esto nos lleva a nuestro próximo tema discreto: combinatoria.
Combinatoria
En pocas palabras, se trata de contar cosas, especialmente al juntar conjuntos en combinaciones o permutaciones.
Por ejemplo, si tienes una aplicación como Tinder, es posible que necesites contar todas las posibles combinaciones de coincidencias como parte de un algoritmo más complejo que determina qué mostrar al usuario final.
O tal vez estás construyendo una base de datos distribuida globalmente y necesitas averiguar cuántas particiones de base de datos necesitarás en todo el mundo.
A fin de cuentas, se trata de entender cómo pueden surgir patrones.
Lo que estás viendo aquí es la fórmula para la secuencia de Fibonacci.
Un gran ejercicio es escribir una función que la genere:
function fibonacci(n) {
if (n <= 1) return n; // Caso base
return fibonacci(n - 1) + fibonacci(n - 2); // Llamada recursiva
}
¡Felicidades! Acabas de hacer combinatoria y desbloquear los secretos del universo.
Los ingenieros en Google utilizan el mismo tipo de lógica para renderizar mosaicos en herramientas como Google Maps.
Teoría de grafos
La combinatoria está muy relacionada con la teoría de grafos.
Un grafo tiene 2 partes básicas:
- nodos (o vértices), y
- aristas, que los conectan entre sí.
Por ejemplo:
- una persona podría ser un nodo, y
- una arista podría ser una relación que los conecta.
Por ejemplo, tú amas a tu mamá y tu mamá te ama a ti.
Este es un grafo no dirigido porque la relación va en ambas direcciones.
Sin embargo, cuando amas a tu novia generada por AI, este sería un grafo dirigido, porque esa relación solo va en una dirección.
Las aristas también pueden tener pesos, lo que significa que una relación es más importante que otra.
Si un nodo puede retroceder a sí mismo, se llama cíclico, de lo contrario se conoce como acíclico.
Como programador, a menudo:
- Necesitarás construir grafos desde cero,
- pero es más importante saber cómo recorrerlos,
- como al usar el algoritmo de Dijkstra,
- para encontrar la forma más eficiente de conducir cuando hay mucho tráfico.
Teoría de la complejidad
Antes de empezar a escribir algoritmos para recorrer grafos, primero debes saber un poco sobre:
La teoría de la complejidad, que puede decirnos en teoría cuánto tiempo y memoria utiliza un algoritmo.
Utilizamos la notación Big O para expresar la complejidad, y al hablar de tiempo, el argumento representa el número de pasos que tomará completar una tarea.
Por ejemplo, si leemos un solo elemento de un arreglo, eso sería O de 1, o tiempo constante, que es súper rápido y simple.
Si necesitamos recorrer un arreglo, eso sería:
- O(n) donde n es la longitud del arreglo,
Pero si en cada iteración de ese bucle, recorremos nuevamente el mismo array, eso sería más bien:
- O(n al cuadrado), lo que sería mucho menos eficiente.
Sin embargo, algoritmos más sofisticados como la búsqueda binaria dividen el área de búsqueda a la mitad después de cada iteración, proporcionándonos tiempo logarítmico.
Comprender cómo medir la complejidad es esencial para las entrevistas técnicas.
Pero ahora dejemos de lado las matemáticas discretas y hablemos de estadística.
Estadística
La estadística es crucial si deseas hacer algo con inteligencia artificial:
Porque machine learning (o aprendizaje automático) es, más o menos, simplemente una forma sofisticada de hacer estadísticas.
Por ejemplo, cuando escribes a ChatGPT, este genera una respuesta basada en probabilidades, buscando lo que mejor se ajuste a la solicitud del usuario.
Como mínimo, deberías entender la media, la mediana y la moda; y cómo la desviación estándar indica qué tan cerca están correlacionados los valores de un conjunto con la media.
Regresión
Hay mucho más temas interesantes por aprender, pero algo especialmente útil es la diferencia entre:
- la regresión lineal, y
- la regresión logística.
En una regresión lineal:
- El objetivo es predecir qué valores continúan, como la cantidad de dinero que perderás después de comprar una acción.
- La relación entre la variable de entrada y la de salida es lineal.
- Y la idea es encontrar una línea que se ajuste mejor al conjunto de datos.
Sin embargo, la regresión logística se utiliza para resolver problemas completamente diferentes, como la clasificación.
Por ejemplo, una aplicación que predice si una imagen es un hot dog o no.
En este caso, la relación no es lineal, sino una función sigmoide, que predice la probabilidad de que una variable booleana sea verdadera o falsa.
Y eso nos lleva a nuestro último tema, tan amado como odiado, el álgebra lineal, que entra en juego cuando se trabaja con computer graphics y deep neural networks.
Álgebra Lineal
Para comprenderlo, necesitas entender estos 3 conceptos.
- Un escalar: es un único valor numérico.
- Un vector: es una lista de números, como un array unidimensional. Y finalmente:
- Una matriz: es como una cuadrícula o un array bidimensional que contiene filas y columnas de valores numéricos.
Lo interesante es que:
- Los vectores pueden representar puntos y direcciones en un espacio tridimensional, mientras que
- las matrices pueden representar transformaciones que ocurren sobre estos vectores.
Cuando mueves un jugador en un videojuego, la iluminación y las sombras en los gráficos cambian mágicamente.
Pero no es magia, es álgebra lineal que se está distribuyendo en tu GPU.
Imagina que tienes un vector 2D que está en el punto 2, 3.
Representa un único punto en una imagen.
Podemos realizar transformaciones lineales aquí, como escalar, trasladar, rotar, transformar geométricamente, y así sucesivamente.
Ahora imaginemos que queremos escalar una imagen desde el punto 2, 3 al punto 4, 6.
Podemos representar los factores de escala en una matriz, luego representar el punto como un vector columna.
Y ahora podemos multiplicar ambas matrices para escalar el punto a su nueva posición.
Operaciones como esta también son esenciales en criptografía, como la encriptación RSA, y también en redes neuronales profundas, que utilizan vectores para representar características, y luego utilizan la multiplicación de matrices para propagar valores entre nodos en la red.
Las matemáticas detrás de esto son sorprendentemente simples, pero se necesita una gran cantidad de poder de cómputo cuando se maneja una enorme cantidad de datos.
Como puedes ver, las matemáticas en realidad no son tan complicadas y cuanto más las estudies, más revelará la computadora sus trucos mágicos.
Gracias por ver leer hasta el final, y nos vemos en una próxima ocasión!