¿Cómo mapeo números, linealmente, entre ayb para ir entre cy d.
Es decir, quiero que los números entre 2 y 6 se asignen a números entre 10 y 20 ... pero necesito el caso generalizado.
Mi cerebro está frito.
¿Cómo mapeo números, linealmente, entre ayb para ir entre cy d.
Es decir, quiero que los números entre 2 y 6 se asignen a números entre 10 y 20 ... pero necesito el caso generalizado.
Mi cerebro está frito.
Respuestas:
Si su número X se encuentra entre A y B, y desea que Y esté entre C y D, puede aplicar la siguiente transformación lineal:
Y = (X-A)/(B-A) * (D-C) + C
Eso debería darle lo que desea, aunque su pregunta es un poco ambigua, ya que también podría mapear el intervalo en la dirección inversa. Solo tenga cuidado con la división por cero y debería estar bien.
Y=f(X)=m*X+b
, donde myb se han determinado simultáneamente a partir de las siguientes dos ecuaciones de restricción que resultan de la sustitución de los valores de X e Y en los puntos finales requeridos: C=m*A+b
yD=m*B+b
X=A+(A-B)*t
para demostrar la igualdad entre este enfoque y el de Peter. Es esencialmente una no dimensionalización de X. ( t=(X-A)/(A-B)
)
Divida para obtener la proporción entre los tamaños de los dos rangos, luego reste el valor inicial de su rango inicial, multiplique por la proporción y agregue el valor inicial de su segundo rango. En otras palabras,
R = (20 - 10) / (6 - 2)
y = (x - 2) * R + 10
Esto distribuye uniformemente los números del primer rango en el segundo rango.
Sería bueno tener esta funcionalidad en la java.lang.Math
clase, ya que es una función muy requerida y está disponible en otros idiomas. Aquí hay una implementación simple:
final static double EPSILON = 1e-12;
public static double map(double valueCoord1,
double startCoord1, double endCoord1,
double startCoord2, double endCoord2) {
if (Math.abs(endCoord1 - startCoord1) < EPSILON) {
throw new ArithmeticException("/ 0");
}
double offset = startCoord2;
double ratio = (endCoord2 - startCoord2) / (endCoord1 - startCoord1);
return ratio * (valueCoord1 - startCoord1) + offset;
}
Estoy poniendo este código aquí como referencia para el futuro y puede que ayude a alguien.
Aparte, este es el mismo problema que el clásico convertir celcius a farenheit donde desea mapear un rango de números que equivale 0 - 100 (C) a 32 - 212 (F).
Cada intervalo de unidad en el primer rango ocupa (dc) / (ba) "espacio" en el segundo rango.
Seudo:
var interval = (d-c)/(b-a)
for n = 0 to (b - a)
print c + n*interval
La forma en que maneja el redondeo depende de usted.
int srcMin = 2, srcMax = 6;
int tgtMin = 10, tgtMax = 20;
int nb = srcMax - srcMin;
int range = tgtMax - tgtMin;
float rate = (float) range / (float) nb;
println(srcMin + " > " + tgtMin);
float stepF = tgtMin;
for (int i = 1; i < nb; i++)
{
stepF += rate;
println((srcMin + i) + " > " + (int) (stepF + 0.5) + " (" + stepF + ")");
}
println(srcMax + " > " + tgtMax);
Con cheques en dividir por cero, por supuesto.
si su rango de [a a b] y desea mapearlo en [c ad] donde x es el valor que desea mapear, use esta fórmula (mapeo lineal)
double R = (d-c)/(b-a)
double y = c+(x*R)+R
return(y)
https://rosettacode.org/wiki/Map_range
[a1, a2] => [b1, b2]
if s in range of [a1, a2]
then t which will be in range of [b1, b2]
t= b1 + ((s- a1) * (b2-b1))/ (a2-a1)