33. Funciones escalonadas

Una función escalonada mantiene un valor constante durante un intervalo y luego salta a otro valor. Es útil para modelar niveles, rangos, tarifas y valores discretos.

33.1 Introducción

Las funciones escalonadas son un caso particular de funciones definidas por tramos. En cada tramo, la salida se mantiene constante.

En programación aparecen cuando convertimos valores continuos en categorías, niveles o cantidades discretas: niveles de experiencia, tarifas por bloques, índices de arreglos, redondeos y cuantización.

33.2 Definición

Una función escalonada es una función por tramos donde cada tramo devuelve un valor constante.

f(x) = 0, si x < 10 f(x) = 1, si 10 ≤ x < 20 f(x) = 2, si x ≥ 20

El gráfico se parece a una escalera: segmentos horizontales separados por saltos.

33.3 Tabla de valores

x Tramo f(x)
5 x < 10 0
10 10 ≤ x < 20 1
19 10 ≤ x < 20 1
20 x ≥ 20 2

33.4 Implementación con condicionales

Una función escalonada se implementa con condiciones que devuelven valores constantes.

function nivel(x) {
  if (x < 10) {
    return 0;
  }

  if (x < 20) {
    return 1;
  }

  return 2;
}

console.log(nivel(5));
console.log(nivel(10));
console.log(nivel(25));

33.5 Función parte entera

Un ejemplo clásico de función escalonada es la función parte entera o piso, que devuelve el mayor entero menor o igual que el número dado.

piso(3.8) = 3 piso(3.1) = 3 piso(-2.3) = -3

En JavaScript se calcula con Math.floor.

33.6 Math.floor en JavaScript

console.log(Math.floor(3.8));
console.log(Math.floor(3.1));
console.log(Math.floor(-2.3));

Para números negativos, Math.floor baja al entero menor, no simplemente elimina los decimales.

33.7 Diferencia entre floor, trunc y round

JavaScript tiene varias funciones relacionadas con redondeo, pero no todas producen el mismo comportamiento.

Función Qué hace Ejemplo con -2.7
Math.floor Entero menor o igual -3
Math.trunc Quita la parte decimal -2
Math.round Redondea al entero más cercano -3

33.8 Cuantizar valores

Cuantizar significa transformar un valor continuo en un nivel discreto. Por ejemplo, convertir una posición en un índice de celda.

celda(x) = piso(x / tamañoCelda)
function indiceCelda(posicion, tamanoCelda) {
  return Math.floor(posicion / tamanoCelda);
}

console.log(indiceCelda(0, 32));
console.log(indiceCelda(31, 32));
console.log(indiceCelda(32, 32));
console.log(indiceCelda(95, 32));

33.9 Aplicación: niveles por puntaje

Una función escalonada puede asignar un nivel según el puntaje acumulado.

function nivelPorPuntaje(puntaje) {
  if (puntaje < 1000) {
    return 1;
  }

  if (puntaje < 3000) {
    return 2;
  }

  if (puntaje < 6000) {
    return 3;
  }

  return 4;
}

console.log(nivelPorPuntaje(800));
console.log(nivelPorPuntaje(2500));
console.log(nivelPorPuntaje(7000));

33.10 Aplicación: tarifas por bloque

Una tarifa puede cambiar de valor según el rango de consumo. Si cada rango devuelve un precio fijo por unidad, estamos usando una función escalonada.

function precioPorUnidad(consumo) {
  if (consumo <= 100) {
    return 10;
  }

  if (consumo <= 300) {
    return 15;
  }

  return 20;
}

console.log(precioPorUnidad(80));
console.log(precioPorUnidad(200));
console.log(precioPorUnidad(400));

33.11 Aplicación: barra de progreso por etapas

Podemos convertir un progreso continuo entre 0 y 1 en una cantidad discreta de etapas.

function etapaProgreso(progreso, cantidadEtapas) {
  const limitado = Math.min(Math.max(progreso, 0), 1);
  return Math.floor(limitado * cantidadEtapas);
}

console.log(etapaProgreso(0.12, 5));
console.log(etapaProgreso(0.5, 5));
console.log(etapaProgreso(1, 5));

El valor se limita entre 0 y 1 antes de calcular la etapa.

33.12 Cuidado con el extremo superior

En el ejemplo anterior, si progreso = 1 y hay 5 etapas, el resultado puede ser 5, aunque los índices válidos podrían ser 0 a 4.

function indiceEtapa(progreso, cantidadEtapas) {
  const limitado = Math.min(Math.max(progreso, 0), 1);
  return Math.min(Math.floor(limitado * cantidadEtapas), cantidadEtapas - 1);
}

console.log(indiceEtapa(0, 5));
console.log(indiceEtapa(0.99, 5));
console.log(indiceEtapa(1, 5));

33.13 Generar una tabla escalonada

Para visualizar una función escalonada podemos generar una tabla de valores.

function escalon(x) {
  return Math.floor(x);
}

for (let x = 0; x <= 4; x += 0.5) {
  console.log(x, escalon(x));
}

33.14 Discontinuidades de salto

Las funciones escalonadas suelen tener discontinuidades de salto. En los puntos donde cambia el escalón, la salida cambia bruscamente.

f(x) = piso(x) cerca de x = 2, la función salta de 1 a 2

Al graficarlas, no conviene unir verticalmente los escalones si queremos representar correctamente la función.

33.15 Aplicaciones en programación

  • Convertir posiciones continuas en índices de grilla.
  • Asignar niveles según puntaje o experiencia.
  • Modelar tarifas por rangos.
  • Cuantizar valores de sensores o controles.
  • Dividir una animación en etapas discretas.

33.16 Errores comunes

  • Confundir función escalonada con función lineal por tramos.
  • Olvidar que la salida se mantiene constante dentro de cada intervalo.
  • Usar Math.floor sin considerar qué ocurre con números negativos.
  • No manejar correctamente el límite superior al calcular índices.
  • Graficar saltos como si fueran líneas continuas.

33.17 Qué debes recordar de este tema

  • Una función escalonada es una función por tramos con valores constantes por intervalo.
  • Su gráfico tiene forma de escalera.
  • Math.floor permite construir funciones escalonadas simples.
  • Los saltos son discontinuidades.
  • Son útiles para niveles, tarifas, grillas, índices y cuantización.
  • Los límites de los intervalos deben definirse con cuidado.

33.18 Conclusión

Las funciones escalonadas son útiles cuando una salida cambia por niveles y no de forma continua. En programación aparecen cada vez que convertimos valores continuos en categorías, bloques o índices.

En el próximo tema comenzaremos con funciones exponenciales, donde el crecimiento depende de multiplicaciones repetidas.