Saltar al contenido

Cómo reducir un rango de números con un valor mínimo y máximo conocido

Esta división ha sido aprobado por nuestros expertos así se garantiza la veracidad de nuestro post.

Solución:

Digamos que quieres escalar un rango [min,max] para [a,b]. Está buscando una función (continua) que satisfaga

f(min) = a
f(max) = b

En tu caso, a sería 1 y b serían 30, pero comencemos con algo más simple e intentemos mapear [min,max] en el rango [0,1].

Poniendo min en una función y salir 0 podría lograrse con

f(x) = x - min   ===>   f(min) = min - min = 0

Eso es casi lo que queremos. pero poniendo en max nos daría max - min cuando en realidad queremos 1. Así que tendremos que escalarlo:

        x - min                                  max - min
f(x) = ---------   ===>   f(min) = 0;  f(max) =  --------- = 1
       max - min                                 max - min

que es lo que queremos. Así que tenemos que hacer una traducción y una escala. Ahora bien, si en cambio queremos obtener valores arbitrarios de a y bnecesitamos algo un poco más complicado:

       (b-a)(x - min)
f(x) = --------------  + a
          max - min

Puedes comprobar que poniendo en min por x ahora da ay poniendo en max da b.

También puede notar que (b-a)/(max-min) es un factor de escala entre el tamaño del nuevo rango y el tamaño del rango original. Así que realmente estamos primero traduciendo x por -minescalándolo al factor correcto y luego traduciéndolo de nuevo al nuevo valor mínimo de a.

Espero que esto ayude.

Aquí hay algo de JavaScript para copiar y pegar fácilmente (esta es la respuesta de irritate):

function scaleBetween(unscaledNum, minAllowed, maxAllowed, min, max) 
  return (maxAllowed - minAllowed) * (unscaledNum - min) / (max - min) + minAllowed;

Aplicado así, escalando el rango de 10-50 a un rango de 0-100.

var unscaledNums = [10, 13, 25, 28, 43, 50];

var maxRange = Math.max.apply(Math, unscaledNums);
var minRange = Math.min.apply(Math, unscaledNums);

for (var i = 0; i < unscaledNums.length; i++) 
  var unscaled = unscaledNums[i];
  var scaled = scaleBetween(unscaled, 0, 100, minRange, maxRange);
  console.log(scaled.toFixed(2));

0,00, 18,37, 48,98, 55,10, 85,71, 100,00

Editar:

Sé que respondí esto hace mucho tiempo, pero aquí hay una función más limpia que uso ahora:

Array.prototype.scaleBetween = function(scaledMin, scaledMax) 
  var max = Math.max.apply(Math, this);
  var min = Math.min.apply(Math, this);
  return this.map(num => (scaledMax-scaledMin)*(num-min)/(max-min)+scaledMin);

Aplicado así:

[-4, 0, 5, 6, 9].scaleBetween(0, 100);

[0, 30.76923076923077, 69.23076923076923, 76.92307692307692, 100]

Para mayor comodidad, aquí está el algoritmo de Irritate en formato Java. Agregue verificación de errores, manejo de excepciones y ajuste según sea necesario.

public class Algorithms  
    public static double scale(final double valueIn, final double baseMin, final double baseMax, final double limitMin, final double limitMax) 
        return ((limitMax - limitMin) * (valueIn - baseMin) / (baseMax - baseMin)) + limitMin;
    

Ensayador:

final double baseMin = 0.0;
final double baseMax = 360.0;
final double limitMin = 90.0;
final double limitMax = 270.0;
double valueIn = 0;
System.out.println(Algorithms.scale(valueIn, baseMin, baseMax, limitMin, limitMax));
valueIn = 360;
System.out.println(Algorithms.scale(valueIn, baseMin, baseMax, limitMin, limitMax));
valueIn = 180;
System.out.println(Algorithms.scale(valueIn, baseMin, baseMax, limitMin, limitMax));

90.0
270.0
180.0

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *