01 · Punto de partida
Un método iterativo necesita saber cuándo terminar
Los métodos numéricos suelen construir una secuencia de aproximaciones. Detenerse demasiado pronto produce un resultado impreciso; continuar innecesariamente consume recursos y puede llegar al límite de la aritmética de punto flotante.
Un ciclo escrito así no contiene una decisión numérica:
while (true) {
aproximacion = mejorar(aproximacion);
}
Necesitamos convertir la idea “suficientemente bueno” en condiciones medibles. Un diseño robusto responde cuatro preguntas:
- ¿Qué cantidad utilizaremos para estimar la calidad?
- ¿Qué umbral resulta apropiado para la escala del problema?
- ¿Qué límites impiden una ejecución interminable?
- ¿Cómo informaremos el motivo de finalización?
02 · Definir lo aceptable
¿Qué es una tolerancia?
Una tolerancia es un límite previamente elegido para una medida de error, residuo o cambio. Si la medida queda por debajo del límite, aceptamos la aproximación según ese criterio.
La tolerancia no es una propiedad universal del algoritmo. Depende de:
Unidades
Una tolerancia absoluta debe expresarse en las mismas unidades que la cantidad evaluada.
Escala
Una diferencia aceptable cerca de 1 puede resultar absurda cerca de 10⁹.
Costo
Exigir más precisión suele requerir más iteraciones, evaluaciones o memoria.
También depende de la precisión de los datos. No tiene sentido exigir un error de 10⁻¹² a un modelo construido con mediciones que solo distinguen centésimas.
03 · Dos escalas complementarias
Tolerancia absoluta y relativa
Una tolerancia absoluta controla una distancia fija:
Funciona bien cerca de cero, pero no se adapta a magnitudes muy diferentes. Una tolerancia relativa escala con el tamaño de los valores:
Cerca de cero, la escala relativa también se aproxima a cero y puede exigir una igualdad imposible. Por eso suelen combinarse:
function cerca(a, b, toleranciaAbsoluta = 1e-12,
toleranciaRelativa = 1e-9) {
if (a === b) return true;
if (!Number.isFinite(a) || !Number.isFinite(b)) return false;
const limite = toleranciaAbsoluta
+ toleranciaRelativa * Math.max(Math.abs(a), Math.abs(b));
return Math.abs(a - b) <= limite;
}
console.log(cerca(0, 1e-13));
console.log(cerca(1e9, 1e9 + 0.1));
También puede usarse el máximo de ambas tolerancias en lugar de la suma. Las dos políticas son válidas si se documentan y se eligen coherentemente.
04 · La medida ideal
Error verdadero
Si conocemos la solución exacta x*, el criterio más directo es:
Este criterio sirve para estudiar y probar un método, pero rara vez está disponible en producción: si conociéramos x*, probablemente no necesitaríamos aproximarlo.
Aun así, los problemas de prueba con solución conocida son importantes para:
- verificar una implementación;
- medir experimentalmente el orden de convergencia;
- comparar criterios estimados con el error real;
- calibrar tolerancias y límites de iteración.
05 · Estabilidad entre iteraciones
Cambio entre aproximaciones sucesivas
Una medida accesible es la diferencia entre las dos últimas aproximaciones:
Podemos aplicar una tolerancia combinada:
function cambioAceptable(anterior, actual, tolAbs, tolRel) {
const cambio = Math.abs(actual - anterior);
const limite = tolAbs + tolRel * Math.abs(actual);
return { aceptado: cambio <= limite, cambio, limite };
}
console.log(cambioAceptable(1.41421356, 1.414213562, 1e-12, 1e-8));
Un cambio pequeño sugiere que la sucesión se estabiliza, pero no garantiza que esté cerca de la solución. Puede existir convergencia lenta, estancamiento de punto flotante o un punto fijo que no resuelve el problema original.
06 · Cumplimiento de la ecuación
Residuo
Al resolver f(x) = 0, el residuo es:
Un criterio posible es rₙ ≤ tolResiduo. Tiene la ventaja de comprobar directamente la ecuación, pero debe interpretarse según su escala y condicionamiento.
Función empinada
Residuo grande cerca de la raíz
Una pendiente elevada transforma un pequeño error en x en un residuo mayor.
Función plana
Residuo pequeño lejos de la raíz
Una pendiente diminuta puede ocultar un error considerable en x.
Cerca de una raíz simple x*, una aproximación de primer orden relaciona ambas medidas:
Por eso, el residuo debe combinarse con información de sensibilidad o con otro criterio.
07 · Garantías del método
Cotas de error e intervalos
Algunos métodos proporcionan una cota teórica. En bisección, si comenzamos con un intervalo de longitud L = b−a, después de n divisiones la longitud es:
El punto medio está como máximo a la mitad de esa longitud de la raíz encerrada. Podemos elegir anticipadamente la cantidad de iteraciones:
function iteracionesBiseccion(inicio, fin, anchoObjetivo) {
if (!(fin > inicio) || !(anchoObjetivo > 0)) {
throw new Error("Intervalo o ancho objetivo inválido");
}
return Math.max(
0,
Math.ceil(Math.log2((fin - inicio) / anchoObjetivo))
);
}
console.log(iteracionesBiseccion(0, 2, 1e-8));
Una cota demostrada ofrece más seguridad que observar únicamente cambios sucesivos. Cada método del curso tendrá sus propias estimaciones y condiciones.
08 · Redes de seguridad
Máximo de iteraciones, tiempo y evaluaciones
Todo algoritmo iterativo debería tener al menos un límite independiente de la convergencia. Las opciones más frecuentes son:
Iteraciones
Detenerse después de una cantidad máxima de actualizaciones.
Evaluaciones
Limitar llamadas costosas a la función o al modelo.
Tiempo
Respetar un presupuesto temporal en aplicaciones interactivas o servicios.
Alcanzar un límite no equivale a converger. El algoritmo debe devolver un estado que permita distinguir una solución aceptada de una finalización por presupuesto agotado.
const resultado = {
valor: aproximacion,
convergio: false,
motivo: "maximo_iteraciones",
iteraciones: 100,
residuo: 2.7e-6
};
09 · Límite de la representación
Detectar estancamiento y ciclos
Puede llegar un momento en que la actualización calculada sea demasiado pequeña para modificar el Number almacenado:
Esto indica estancamiento numérico, no necesariamente éxito. Debemos comprobar el residuo u otra medida antes de declarar convergencia.
También pueden aparecer ciclos cortos, por ejemplo a → b → a → b. Guardar las últimas aproximaciones permite detectar algunos casos.
function estadoActual(anterior, actual, haceDos, residuo, tolerancia) {
if (residuo <= tolerancia) return "convergencia";
if (actual === anterior) return "estancamiento";
if (actual === haceDos) return "ciclo_de_periodo_2";
return "continuar";
}
10 · Decisiones robustas
Combinar criterios
Un solucionador puede observar simultáneamente cambio, residuo, cota e iteraciones. La forma de combinarlos expresa una política:
| Política | Condición | Consecuencia |
|---|---|---|
| Permisiva | Cambio pequeño o residuo pequeño | Puede detenerse antes, con menos garantías |
| Conservadora | Cambio pequeño y residuo pequeño | Exige evidencia de ambos tipos |
| Con cota | Cota teórica menor que tolerancia | Utiliza la garantía específica del método |
| Seguridad | Máximo alcanzado o valor no finito | Finaliza sin declarar convergencia |
No existe una combinación universal. Para una raíz, puede ser razonable exigir residuo y cambio pequeños. Para bisección, el ancho del intervalo ofrece una garantía directa. Para una simulación en tiempo real, el presupuesto temporal puede dominar.
11 · Patrón de implementación
Un ciclo iterativo robusto
El siguiente patrón separa actualización, evaluación y finalización:
function resolverIterativamente({
inicial,
actualizar,
residual,
toleranciaAbsoluta = 1e-12,
toleranciaRelativa = 1e-9,
toleranciaResiduo = 1e-10,
maxIteraciones = 100
}) {
let anterior = inicial;
for (let iteracion = 1; iteracion <= maxIteraciones; iteracion++) {
const actual = actualizar(anterior);
const residuo = Math.abs(residual(actual));
if (!Number.isFinite(actual) || !Number.isFinite(residuo)) {
return { valor: actual, convergio: false,
motivo: "valor_no_finito", iteracion, residuo };
}
const cambio = Math.abs(actual - anterior);
const limiteCambio = toleranciaAbsoluta
+ toleranciaRelativa * Math.abs(actual);
if (cambio <= limiteCambio && residuo <= toleranciaResiduo) {
return { valor: actual, convergio: true,
motivo: "tolerancias", iteracion, cambio, residuo };
}
if (actual === anterior) {
return { valor: actual, convergio: false,
motivo: "estancamiento", iteracion, cambio, residuo };
}
anterior = actual;
}
return { valor: anterior, convergio: false,
motivo: "maximo_iteraciones", iteracion: maxIteraciones };
}
La función no oculta los fallos: devuelve un diagnóstico estructurado para que la aplicación decida si reintenta, cambia de método o informa al usuario.
12 · Aplicación
Aproximar una raíz cuadrada
Para aproximar √S utilizamos la actualización babilónica:
El residuo de la ecuación x² − S = 0 es |x² − S|. Podemos aplicar el patrón anterior:
const numero = 2;
const resultado = resolverIterativamente({
inicial: 1,
actualizar: x => (x + numero / x) / 2,
residual: x => x * x - numero,
toleranciaAbsoluta: 1e-12,
toleranciaRelativa: 1e-10,
toleranciaResiduo: 1e-12,
maxIteraciones: 50
});
console.log(resultado);
La tolerancia del cambio está expresada en unidades de x; la del residuo, en unidades de x². Aunque ambas tengan valores numéricos parecidos, representan cantidades distintas.
13 · Exploración interactiva
Laboratorio: comparar criterios de parada
Aproximaremos √2 y podremos detenernos por cambio, residuo o ambos. Variá la tolerancia y el máximo de iteraciones para observar el motivo de finalización.
¿Cuándo detener la iteración?
tolerancia = 10⁻⁸
El método alcanzó las condiciones solicitadas.
Preguntas para explorar
- Reducí el máximo a dos iteraciones. ¿Cómo informa el laboratorio la salida?
- ¿Cuántas iteraciones adicionales exige pasar de
10⁻⁴a10⁻¹²? - Compará “cambio y residuo” con “cambio o residuo”.
- Probá
10⁻¹⁵. ¿Aparece alguna limitación de punto flotante?
14 · Diseño de interfaces
Informar más que un número
Una API numérica debería devolver suficiente información para auditar la decisión:
| Campo | Propósito |
|---|---|
valor | Mejor aproximación disponible. |
convergio | Distingue éxito numérico de finalización forzada. |
motivo | Tolerancia, cota, estancamiento, límite o valor inválido. |
iteraciones | Costo y diagnóstico de convergencia. |
cambio | Diferencia entre las últimas aproximaciones. |
residuo | Cumplimiento de la ecuación original. |
historial | Opcional para gráficos, depuración y análisis. |
Es preferible devolver el mejor valor junto con una advertencia que devolver null sin contexto. La aplicación puede decidir si el resultado parcial es útil.
15 · Comprensión
Confusiones frecuentes
«Una tolerancia pequeña siempre mejora el resultado»
Puede aumentar el costo sin aportar precisión si los datos, el condicionamiento o el punto flotante ya establecen un límite.
«Residuo pequeño significa error pequeño»
La relación depende de la sensibilidad del problema. Una función plana puede tener residuo pequeño lejos de la raíz.
«Si actual === anterior, el método convergió»
La igualdad puede significar estancamiento. Debe comprobarse el residuo, una cota u otra condición.
«Máximo de iteraciones es un criterio de convergencia»
Es una medida de seguridad o presupuesto. Alcanzarlo no permite declarar que la aproximación satisface la precisión.
«La misma tolerancia sirve para cualquier unidad»
Una tolerancia absoluta de 0.01 tiene significados distintos en metros, segundos o dólares. Debe vincularse al dominio.
16 · Práctica guiada
Ejercicios
Ejercicio 1: tolerancia combinada
Para a = 1 000 000, b = 1 000 000.005, tolAbs = 0.001 y tolRel = 10⁻⁸, determiná si cumplen |a−b| ≤ tolAbs + tolRel·max(|a|,|b|).
Ver solución
La diferencia es aproximadamente 0.005. El límite es 0.001 + 0.01 = 0.011 aproximadamente. Por lo tanto, los valores se aceptan según esta política.
Ejercicio 2: iteraciones de bisección
¿Cuántas divisiones se necesitan para reducir un intervalo de longitud 4 a un ancho máximo de 10⁻⁶?
Ver solución
n ≥ ceil(log₂(4/10⁻⁶)) = ceil(log₂(4 000 000)) = 22. Después de 22 divisiones, el ancho es menor o igual que el solicitado.
Ejercicio 3: elegir criterios
Para encontrar una raíz de f(x)=0, proponé una política que combine cambio, residuo y máximo de iteraciones.
Ver una posible respuesta
Declarar convergencia cuando el cambio satisfaga tolerancias absoluta y relativa y el residuo esté por debajo de su tolerancia. Detener sin declarar convergencia al alcanzar el máximo, obtener un valor no finito o detectar estancamiento con residuo inaceptable.
Ejercicio 4: detectar un fallo
Un algoritmo devuelve el mismo valor en dos iteraciones, pero el residuo es 0.4 y la tolerancia de residuo es 10⁻⁸. ¿Qué estado debería informar?
Ver solución
Debe informar estancamiento sin convergencia. La igualdad entre iteraciones no compensa el residuo inaceptable.
Ejercicio 5: implementar un resultado
Escribí una función que construya un objeto de resultado uniforme para convergencia, máximo de iteraciones o valor no finito.
Ver una posible solución
function crearResultado(valor, iteraciones, motivo, diagnostico = {}) {
const motivosExitosos = new Set(["tolerancia", "cota"]);
return {
valor,
iteraciones,
motivo,
convergio: motivosExitosos.has(motivo),
...diagnostico
};
}
console.log(crearResultado(1.4142, 6, "tolerancia", {
cambio: 2e-10,
residuo: 3e-12
}));
17 · Síntesis
Ideas para recordar
- Una tolerancia convierte “suficientemente bueno” en una condición medible.
- Las tolerancias absolutas funcionan cerca de cero; las relativas se adaptan a la escala.
- El cambio entre iteraciones, el residuo y las cotas miden aspectos diferentes.
- Ningún criterio observable garantiza por sí solo un error verdadero pequeño.
- Todo ciclo iterativo necesita un límite de seguridad independiente de la convergencia.
- Estancamiento e igualdad entre iteraciones no son sinónimos de éxito.
- Combinar criterios aumenta la robustez cuando sus escalas están bien definidas.
- El resultado debe incluir valor, estado, motivo, iteraciones y diagnósticos.
En el próximo tema comenzaremos la unidad de raíces de ecuaciones no lineales: cómo formular f(x)=0, localizar intervalos candidatos y visualizar las soluciones.