Відповіді:
Якщо ваше число X потрапляє між A і B, і ви хотіли б, щоб Y падало між C і D, ви можете застосувати наступне лінійне перетворення:
Y = (X-A)/(B-A) * (D-C) + C
Це має дати вам те, що ви хочете, хоча ваше питання трохи неоднозначне, оскільки ви також можете відобразити інтервал у зворотному напрямку. Просто стежте за діленням на нуль, і у вас все буде в порядку.
Y=f(X)=m*X+b
, де m і b були визначені одночасно з наступних двох рівнянь обмеження, які є результатом підстановки значень X і Y у необхідні кінцеві точки: C=m*A+b
іD=m*B+b
X=A+(A-B)*t
щоб довести рівність між цим підходом і підходом Петра. це, по суті, недименсіоналізація X. ( t=(X-A)/(A-B)
)
Розділіть, щоб отримати співвідношення між розмірами двох діапазонів, потім відніміть початкове значення вашого початкового діапазону, помножте на відношення і додайте початкове значення вашого другого діапазону. Іншими словами,
R = (20 - 10) / (6 - 2)
y = (x - 2) * R + 10
Це рівномірно розподіляє числа з першого діапазону у другий діапазон.
Було б непогано мати цю функцію в java.lang.Math
класі, оскільки це така необхідна функція, яка доступна іншими мовами. Ось проста реалізація:
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;
}
Я розміщую цей код тут як орієнтир для себе в майбутньому, і, можливо, він комусь допоможе.
Окрім того, це та сама проблема, що і класичне перетворення Цельсія у Фаренгейт, де потрібно зіставити діапазон чисел, який дорівнює 0 - 100 (C) до 32 - 212 (F).
Кожен одиничний інтервал на першому діапазоні займає (dc) / (ba) "простір" на другому діапазоні.
Псевдо:
var interval = (d-c)/(b-a)
for n = 0 to (b - a)
print c + n*interval
Як ви обробляєте округлення, вирішувати вам.
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);
Звісно, з чеками на ділення на нуль.
якщо ваш діапазон від [a до b], і ви хочете зіставити його в [c до d], де x - значення, яке ви хочете зіставити, використовуйте цю формулу (лінійне відображення)
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)