2008-12-05 13 views
65

¿Cómo puedo mapear números, linealmente, entre a y b para ir entre c y d.Matemáticas - números de mapeo

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.

+3

Forma de dos puntos. http://en.wikipedia.org/wiki/Linear_equation#Two-point_form – kennytm

Respuesta

16

Divide para obtener la relación entre los tamaños de los dos rangos, luego resta el valor inicial de tu rango inicial, multiplica por la razón y agrega el valor inicial de tu 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.

+0

Esto no funciona. Mi rango es de 1000000000 a 9999999999 y los números pueden ser de 1 a 999999999. – Dejell

+0

@Odelya Por supuesto que funciona. Es una transformación matemática lo suficientemente simple. Solo necesita usar un tipo de número lo suficientemente grande (bignum o similar). Sus números son simplemente demasiado grandes para enteros de 32 bits, pero los enteros de 64 bits, por ejemplo, funcionarán. –

+0

Son de tipo doble. doble R = (20 - 10)/(6 - 2); \t \t doble y = (X - 2) * R + 10; – Dejell

137

Si el número de X cae entre A y B, y que le gustaría Y caiga entre C y D, se puede aplicar la siguiente transformación lineal:

Y = (XA)/(BA) * (DC) + C

Eso debería darle lo que quiere, aunque su pregunta es un poco ambigua, ya que también puede asignar el intervalo en la dirección inversa. Solo ten cuidado con la división por cero y deberías estar bien.

+0

Gracias. Exactamente lo que estaba buscando. – Sam

+31

Luego, tal vez marque esta respuesta como "aceptada" haciendo clic en la marca de verificación junto a ella. –

+0

Gracias Peter, eres fantástico! – Adi

1

Cada intervalo de unidad en el primer rango ocupa (d-c)/(b-a) "espacio" en el segundo rango.

Pseudo:

var interval = (d-c)/(b-a) 
for n = 0 to (b - a) 
    print c + n*interval 

¿Cómo manejar el redondeo depende de usted.

1
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 controles en dividir por cero, por supuesto.

2

Como un lado, este es el mismo problema que el clásico convertir celcius a farenheit en el que desea asignar un rango numérico que equivale a 0 - 100 (C) a 32 - 212 (F).

+0

¿Cómo es esta una respuesta? – shinzou

+0

Es un ejemplo de la aplicación de la pregunta. Muchos tienen este problema simple en las clases introductorias de CS y no consideran que la solución se pueda generalizar a otros problemas. Estaba tratando de agregar contexto a la pregunta original. La pregunta original ya había sido respondida adecuadamente. – Metro

0

Además de respuesta @PeterAllenWebb, si desea volver a revertir el resultado, utilice la siguiente:

reverseX = (B-A)*(Y-C)/(D-C) + A 
1

Sería bueno tener esta funcionalidad en la clase java.lang.Math, ya que esto es un ejemplo ampliamente función requerida y está disponible en otros idiomas. Aquí es una aplicación sencilla:

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 mí y puede ser que ayude a alguien.