La PizarraMatemática.

Matemáticas para ingeniería

Programación de algoritmos matemáticos reproducibles

Un algoritmo es una receta precisa: recibe datos, realiza pasos y devuelve un resultado. Antes de escribir código, haremos la receta a mano con pocas entradas. Después explicaremos por qué funciona, cómo detectamos errores y qué hay que guardar para que otra persona pueda repetir el cálculo. Repetir un resultado y que ese resultado responda bien al problema son dos comprobaciones diferentes.

1. El contrato dice qué entra, qué sale y qué casos se rechazan

Una petición como «suma estos números» necesita límites, tipo de dato y significado. Fijamos el dominio de entrada, la salida esperada, unidades y tratamiento de casos vacíos o inválidos. La receta solo puede ser correcta respecto de una tarea definida.

Usaremos S(n)=Σₖ₌₁ⁿk² para enteros n≥0.

El cuadrado pertenece al término, no al total de la suma.

Declaramos S(0)=0 como suma vacía.

Un n negativo o no entero se rechaza: no se convierte silenciosamente en otro problema.

Leer la definición antes de recorrer índices

Calcular S(3)=Σₖ₌₁³k².

  1. Índices

    Los valores de k son uno, dos y tres; no cero a dos.

  2. Términos

    Son 1²=1, 2²=4 y 3²=9.
  3. Salida

    S(3)=1+4+9=14.
    (1+2+3)²=36 sería otra expresión.
Resultado

La salida pedida es 14.

Lo comprobamos

Tres términos no significa tres veces el último término.

La frontera del dominio también se diseña

¿Qué debe hacer la receta con n=0, n=−1 y n=3,5?

  1. Vacío admitido

    Para cero, el recorrido de uno a cero no procesa términos y devuelve el acumulador inicial cero.

  2. Negativo

    −1 está fuera del dominio; se informa entrada inválida en vez de devolver un número como si fuera S(−1).

  3. Fracción

    3,5 tampoco es entero. Redondearlo a tres o cuatro cambiaría el contrato y requeriría otra regla explícita.

Resultado

Una receta completa incluye sus casos límite y su rechazo.

Lo comprobamos

Rechazar datos fuera del dominio es un comportamiento correcto, no un fallo de convergencia.

2. La actualización debe usar los valores que exige la definición

Para S(n), iniciamos s=0, recorremos k de uno a n y hacemos s nuevo=s antiguo+k². El estado s representa una suma parcial. Una variable de recorrido y una de estado tienen funciones diferentes, aunque ambas sean números.

Actualizar dos estados requiere conservar los valores antiguos
Antes: (a, b)=(2,3)Queremos (b, a+b)Nuevo aNuevo bb antiguoa+b antiguos35Guardamos primero los dos nuevos.Después sustituimos (a, b).Usar a nuevo en b daría 3+3=6.
Si el par anterior es dos y tres, el siguiente debe ser tres y cinco. Los dos cálculos usan el par antiguo. Si primero se reemplaza a por tres y después se calcula b usando ese a nuevo, saldría seis y se alteraría la recurrencia.

Cuando hay varios estados, calculamos primero los nuevos valores usando una copia de los anteriores. Sustituir un estado demasiado pronto puede cambiar la recurrencia. No basta con que en el programa aparezcan las mismas letras que en la fórmula.

Hacer la suma como una tabla de estados

Calcular S(4) con acumulador s.

  1. Inicio

    Antes de procesar términos, s=0.
  2. Actualizaciones

    Tras k=1,2,3,4, los estados son 1, 5, 14 y 30.
  3. Devolver

    Al terminar se devuelve 30, el último acumulador; no el contador final ni el término 4²=16.

Resultado

La tabla deja visible qué representa s en cada momento.

Lo comprobamos

La diferencia entre estados consecutivos es exactamente k².

Dos números de Fibonacci se actualizan como un par

Estado inicial (a, b)=(0,1); cada paso debe producir (b, a+b).

  1. Primeros pares

    Los estados correctos son (1,1), (1,2), (2,3), (3,5).

    Tras cuatro pasos, a=3.
  2. Conservar lo antiguo

    Desde (2,3), los nuevos valores son tres y cinco, ambos calculados con el par anterior.

  3. Error de orden

    Si se hace a←b y luego b←a+b usando a ya cambiado, desde (2,3) se obtiene (3,6). La receta ya no es la misma.

Resultado

La asignación simultánea o dos temporales conservan la recurrencia.

Lo comprobamos

Los nombres de las variables no protegen contra usar un valor de otra etapa.

3. Un invariante explica todas las filas de un bucle, no solo una tabla

Un invariante es una relación verdadera antes y después de cada paso. Para demostrarlo comprobamos inicio, conservación y conclusión al parar. Además justificamos terminación: una propiedad que se conserva no garantiza por sí sola que la receta llegue al final.

Un invariante conecta cada fila con la definición
Sumar impares construye cuadradosDespués de k pasos: s=k²ksañadir001113245397416fink² + 2k + 1 = (k+1)²Cada paso conserva la misma relación.
Para sumar los primeros n impares, se comienza con k cero y suma cero. Se añaden uno, tres, cinco y siete. Después de cada paso, la suma es k al cuadrado: cero, uno, cuatro, nueve y dieciséis. La identidad k cuadrado más dos k más uno igual a k más uno al cuadrado demuestra la conservación para cualquier paso.

Para sumar los primeros n impares usaremos k=0, s=0; mientras k<n, añadimos 2k+1 a s y después aumentamos k en uno.

El invariante es s=k².

La cantidad entera n−k baja en cada paso y nunca es negativa durante el recorrido admitido.

Demostrar la suma de impares mediante su actualización

Queremos 1+3+…+(2n−1)=n² para n≥0 entero.

  1. Inicio

    Con k=0 y s=0 se cumple s=k².
  2. Conservación

    Si antes s=k², al añadir 2k+1 queda s nuevo=k²+2k+1=(k+1)².

    Aumentar k conserva la relación.

  3. Final

    El bucle termina en k=n porque k aumenta hasta un límite entero finito.

    El invariante da s=n², la salida deseada.
Resultado

La misma identidad demuestra cualquier cantidad de pasos admitida.

Lo comprobamos

La tabla para n=4 da 1+3+5+7=16, coherente con la demostración general.

Un bucle puede conservar algo y no terminar

La tarea exige llegar de k=0 a n=−1 aumentando k en uno hasta que k=n.

  1. Recorrido

    Los índices serían 0,1,2,3,…: nunca llegan a menos uno.

  2. Invariante posible

    Que k sea entero no resuelve ese problema de terminación.

  3. Contrato

    Nuestro dominio n≥0 y una condición k<n evitan esta receta inválida. Cambiar el dominio requiere volver a justificar el recorrido.

Resultado

Corrección parcial y terminación son obligaciones separadas.

Lo comprobamos

Un límite máximo de pasos permite detener un programa defectuoso, pero no lo convierte en una solución correcta.

4. Las pruebas necesitan una referencia independiente y casos que puedan fallar

Una prueba compara una salida con una referencia calculada de otro modo: una cuenta a mano, una identidad demostrada o una solución exacta. Reescribir el mismo bucle con otro nombre puede repetir su error. Las pruebas finitas detectan fallos; no sustituyen una demostración general.

También comprobamos relaciones entre entradas. Para S(n), S(n+1)−S(n)=(n+1)² debe cumplirse, y S(0)=0 fija el caso inicial. Fronteras, entradas inválidas y signos especiales complementan los ejemplos típicos.

Contrastar una suma con una fórmula demostrada por otro camino

Comprobar S(4) usando n(n+1)(2n+1)/6.

  1. Sustituir

    4·5·9/6=180/6=30.
  2. Comparar

    La tabla del bucle dio 30. Un bucle que omitiera el último término devolvería 14 y se detectaría.

  3. Frontera

    Para n=0, fórmula y suma vacía dan cero. La coincidencia en esos casos no reemplaza la prueba de conservación para todo n.

Resultado

La referencia no recorre de nuevo exactamente los mismos términos.

Lo comprobamos

La fórmula también tiene un dominio y debe evaluarse sin desbordamiento en el tipo elegido.

Una relación entre ejecuciones detecta un término perdido

Un programa devuelve T(3)=14 y T(4)=29 para la suma de cuadrados.

  1. Diferencia observada

    29−14=15.
  2. Relación esperada

    El término nuevo debe ser 4²=16.
  3. Diagnóstico

    Al menos uno de esos resultados es incorrecto. La relación detecta una inconsistencia sin conocer de antemano todas las salidas posibles.

Resultado

Una comprobación matemática puede contrastar varias ejecuciones.

Lo comprobamos

Pasar esa relación en pocos índices no prueba que el programa la cumpla en todos.

5. El tipo numérico y el orden de operaciones forman parte del cálculo

La matemática exacta puede trabajar con enteros ilimitados y reales ideales. Un programa usa tipos con rango y precisión definidos. Un entero pequeño puede desbordarse; una suma en coma flotante puede perder un sumando pequeño. No se interpreta cada discrepancia como un fallo de la fórmula matemática.

Para comparar aproximaciones es frecuente exigir |a−b|≤atol+rtol·|b|, donde b es la referencia declarada. La parte relativa sigue su escala; la absoluta sirve cerca de cero. Las tolerancias se eligen según el propósito y la precisión disponible, no para forzar que cualquier resultado parezca correcto.

La asociación de una suma cambia el resultado en binary64

Tomar L=2⁵³ y sumar L, uno y −L en coma flotante binary64 con redondeo al más próximo, empates al par.

  1. Primero el pequeño

    L+1 queda a mitad entre dos representables y se redondea a L. Así (L+1)−L da cero.

  2. Primero cancelar

    (L−L)+1 da uno.

  3. Exacto

    La suma matemática de los tres números es uno en ambos órdenes. La diferencia procede de una operación intermedia redondeada.

Resultado

Igualdad algebraica no implica idéntico resultado redondeado.

Lo comprobamos

No se afirma que todo tipo de precisión arbitraria tenga este mismo umbral L.

Una tolerancia relativa y otra absoluta resuelven escalas diferentes

atol=10⁻⁸, rtol=10⁻⁵.

  1. Valor grande

    Con referencia b=1 000 000 y a=1 000 004, el error cuatro está bajo el umbral 10+10⁻⁸.

  2. Cerca de cero

    Con b=0 y a=10⁻⁷, el umbral es solo 10⁻⁸.

    No pasa esta comprobación.

  3. Interpretar

    El mismo error absoluto no tiene el mismo significado a cualquier escala. Cerca de cero la referencia relativa no aporta margen.

Resultado

La regla de comparación declara qué precisión se exige.

Lo comprobamos

No se divide por b cuando la referencia puede ser cero.

Un rango entero limitado puede cambiar una suma exacta

Sumar de uno a 23 con un entero sin signo de ocho bits y aritmética modular de 256 estados.

  1. Exacto

    23·24/2=276.
  2. Rango

    Los valores representables son cero a 255; 276 no cabe.

  3. Regla declarada

    En esta aritmética modular, 276 mod 256=20.

    Otro entorno podría rechazar el desbordamiento; se necesita conocer la regla del tipo utilizado.

Resultado

Para devolver 276 se elige un tipo con rango suficiente.

Lo comprobamos

El ejemplo no atribuye envolvimiento modular a cualquier tipo entero de cualquier lenguaje.

6. Incremento, residual y error se relacionan solo con hipótesis

El incremento mide cuánto cambia una aproximación. El residual mide cuánto incumple una ecuación. El error compara con la solución verdadera. Son preguntas diferentes. Una parada debe informar qué condición se cumplió y si se alcanzó un límite de iteraciones o apareció un fallo numérico.

Si x siguiente=g(x) es una contracción global en el dominio adecuado con constante q<1, el error del nuevo punto es como máximo q/(1−q) veces el último incremento. Esta cota necesita la contracción, no solo observar que dos números impresos se parecen.

Un paso diminuto puede quedarse lejos de la raíz

F(x)=x−100, x₀=0; actualizar x₁=x₀−10⁻⁸F(x₀).

  1. Paso

    F(0)=−100 y x₁=10⁻⁶.

    El incremento es 10⁻⁶, menor que 10⁻³.

  2. Error

    La raíz es cien. El error es 100−10⁻⁶, casi cien.

  3. Residual

    |F(x₁)| también es casi cien. Parar solo por el incremento habría confundido paso pequeño con solución precisa.

Resultado

Moverse poco no certifica estar cerca.

Lo comprobamos

La regla de actualización fue intencionadamente mal escalada.

Un residual pequeño también depende de la escala de la ecuación

F(x)=10⁻⁶(x−1), evaluada en x=0.

  1. Residual

    |F(0)|=10⁻⁶.
  2. Error

    La solución es uno y el error vale uno.

  3. Relación

    Aquí |x−1|=10⁶|F(x)|.

    El factor inverso explica por qué la cifra residual no se traduce directamente en error pequeño.

Resultado

Una ecuación escalada exige interpretar la escala del residual.

Lo comprobamos

Multiplicar una ecuación por una constante no cambia su raíz, pero sí su residual numérico.

Una contracción sí aporta una cota de error a partir del cambio

g(x)=x/2+1, con constante q=1/2 y punto fijo dos.

  1. Iterados

    Desde cero se obtiene 1, 3/2, 7/4,…

  2. Último paso

    Del segundo al tercero, el incremento es 1/4.

  3. Cota

    q/(1−q)=1, así el error del tercero es como máximo 1/4.

    En efecto, 2−7/4=1/4: aquí la cota se alcanza.
Resultado

La garantía procede de una propiedad demostrada de g.

Lo comprobamos

La fórmula se aplica al punto nuevo; para el punto anterior la cota correspondiente lleva otro factor.

7. Para reproducir una ejecución guardamos datos y decisiones, no solo una semilla

Un experimento reproducible conserva datos de entrada, transformaciones, código, parámetros, tipos numéricos, tolerancias, dependencias y forma de ejecución. Si hay aleatoriedad, conserva el generador y su estado inicial; si hay trabajo paralelo, también el reparto de secuencias y el orden de reducción cuando importa.

Se declara el objetivo: identidad bit a bit o acuerdo dentro de una tolerancia. Cambiar biblioteca, hardware o el orden de una suma paralela puede cambiar redondeos. Una semilla repetida permite reconstruir cierta secuencia, pero no demuestra independencia estadística, precisión ni validez del modelo.

La misma semilla con otra regla genera otros datos

Generador didáctico s siguiente=(5s+1) mod 16, con s₀=3.

  1. Primera secuencia

    Los estados siguientes son 0, 1, 6 y 15.

  2. Otra regla

    Con s siguiente=(3s+1) mod 16 y la misma semilla tres, serían 10, 15, 14 y 11.

  3. Registrar

    Hay que guardar regla y semilla. Este generador pequeño ilustra el estado: no se propone como generador adecuado para simulación científica o seguridad.

Resultado

Semilla sin especificación del generador no identifica la secuencia.

Lo comprobamos

Todos los estados quedan entre cero y quince por el módulo declarado.

Partir una simulación exige repartir la secuencia sin reiniciarla por accidente

Usar el primer generador y generar dos bloques de dos estados.

  1. Ejecución continua

    Desde tres salen [0;1;6;15]. Tras el primer bloque, el estado guardado es uno.

  2. Continuar

    Iniciar el segundo bloque desde ese estado uno produce [6;15].

  3. Reiniciar

    Volver a semilla tres en el segundo bloque produce [0;1] otra vez. Concatenar [0;1;0;1] no reproduce la ejecución continua.

Resultado

Los estados y el reparto entre bloques forman parte del experimento.

Lo comprobamos

Un esquema paralelo puede usar subflujos distintos, pero debe declarar cómo los construye.

8. Verificar el programa y validar el modelo responden preguntas distintas

Verificar pregunta si calculamos correctamente la tarea matemática. Validar pregunta si esa tarea representa la situación real que queríamos estudiar. Un resultado repetible puede estar perfectamente calculado dentro de un modelo inadecuado.

Una salida útil conserva valor, unidades, estado de terminación y una comprobación interpretable. Para una raíz puede devolver un intervalo certificado además de una aproximación; para una simulación, supuestos y medidas de error. Una gráfica bonita no sustituye esos datos.

La fórmula correcta puede aplicarse al movimiento equivocado

Un programa calcula d=vt para velocidad constante; v=2 m/s y t=3 s.

  1. Verificación

    2·3=6 m: el programa cumple esa fórmula y sus unidades.

  2. Otra situación

    Si el objeto parte del reposo con aceleración constante 1 m/s², el modelo adecuado da d=(1/2)at²=4,5 m.

  3. Validación

    Usar seis metros en esa segunda situación falla por la hipótesis de velocidad constante, aunque la multiplicación esté bien programada.

Resultado

Un cálculo correcto no decide si sus supuestos describen el fenómeno.

Lo comprobamos

Además, 18 km/h equivale a 5 m/s; en tres segundos son 15 m, no 54 m por mezclar unidades.

Un intervalo expresa una garantía concreta de una aproximación

Para √2 se ha verificado un intervalo [1,414;1,415] con extremos de signos opuestos en F(x)=x²−2.

  1. Extremos

    1,414²−2=−0,000604 y 1,415²−2=0,002225.
  2. Garantía

    Por continuidad y crecimiento de x² en ese intervalo hay una única raíz dentro.

  3. Salida

    El punto medio 1,4145 tiene error absoluto como máximo 0,0005. Se devuelve el intervalo y la condición cumplida, además del decimal.

Resultado

La precisión se justifica con el ancho y la localización de la raíz.

Lo comprobamos

La cota no se obtiene por contar cuántos decimales se imprimieron.

Ahora lo resolvemos de principio a fin.

EJEMPLO RESUELTO 1

Comprobar un bucle

Un algoritmo suma enteros de 1 a n. Verifica el caso n=4.

  1. Contrato

    Se suman los enteros de uno a n, ambos límites incluidos.

    Para n=4 son 1,2,3,4.
  2. Estado inicial

    El acumulador comienza en cero, antes de procesar términos.

  3. Primeras filas

    Tras añadir uno y después dos, vale uno y tres.

  4. Últimas filas

    Al añadir tres queda seis; al añadir cuatro queda diez.

  5. Referencia independiente

    La fórmula n(n+1)/2 da 4·5/2=10.
  6. Frontera

    Si el contrato incluye n=0, la suma vacía devuelve cero. La prueba de ese caso evita exigir un primer término inexistente.

Resultado

Resultado 10.

Lo comprobamos

Prueba también n=0 si el dominio incluye la suma vacía, cuyo valor es cero.

EJEMPLO RESUELTO 2

Registrar una tolerancia

Un algoritmo se detiene cuando |xₖ₊₁−xₖ|≤10⁻³. Los últimos valores son 1,414 y 1,4142. ¿Cumple el criterio?

  1. Criterio

    La parada propuesta compara el incremento con 10⁻³=0,001.
  2. Valores

    El punto anterior es 1,414 y el nuevo es 1,4142.

  3. Diferencia

    |1,4142−1,414|=0,0002.
  4. Comparar

    0,0002≤0,001: sí se cumple el criterio del incremento.
  5. Alcance

    La comparación no usa la solución exacta y no certifica por sí sola el error respecto de ella.

  6. Informe

    Se registra parada por incremento, valor nuevo y residual si hay ecuación definida. Una cota de error necesita una relación adicional demostrada, como una contracción conocida.

Resultado

Sí cumple el criterio del incremento.

Lo comprobamos

Esto no certifica por sí solo el error respecto de la solución exacta; conviene revisar también el residual.

Los símbolos que hemos usado

Algoritmo
Procedimiento finito y especificado para transformar entradas válidas en resultados.
Precondición / poscondición
Requisito de entrada / propiedad que debe cumplir la salida.
Invariante
Propiedad que se conserva al avanzar un bucle.
Residual
Medida de cuánto incumple una aproximación la ecuación planteada.
Tolerancia
Umbral declarado para decidir si una magnitud es suficientemente pequeña.
Semilla
Estado inicial o dato usado para inicializar una secuencia pseudoaleatoria.

Ahora te toca a ti.

Tienes cinco ejercicios. Inténtalos; las pistas te ayudan si te atascas.

Practicar este tema →

Para ampliar