如何在 a 和 b 之间线性映射数字以在 c 和 d 之间移动。
也就是说,我希望 2 到 6 之间的数字映射到 10 到 20 之间的数字......但我需要广义的情况。
我的大脑被炸了。
如何在 a 和 b 之间线性映射数字以在 c 和 d 之间移动。
也就是说,我希望 2 到 6 之间的数字映射到 10 到 20 之间的数字......但我需要广义的情况。
我的大脑被炸了。
如果您的数字 X 介于 A 和 B 之间,并且您希望 Y 介于 C 和 D 之间,则可以应用以下线性变换:
Y = (X-A)/(B-A) * (D-C) + C
这应该给你你想要的,虽然你的问题有点模棱两可,因为你也可以在相反的方向上映射间隔。只要注意被零除,你应该没问题。
除以得到两个范围大小之间的比率,然后减去初始范围的起始值,乘以比率并添加第二个范围的起始值。换句话说,
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) 的数字范围。
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)
除了@PeterAllenWebb 答案,如果您想反转结果,请使用以下命令:
reverseX = (B-A)*(Y-C)/(D-C) + A
第一个范围上的每个单位间隔占用第二个范围上的 (dc)/(ba)“空间”。
伪:
var interval = (d-c)/(b-a)
for n = 0 to (b - a)
print c + n*interval
如何处理舍入取决于您。
其中X是从A - B映射到C - D的数,Y是结果:采用线性插值公式,lerp( a , b , m )= a +( m *( b - a )),并且用C和D代替a和b得到Y = C +( m *( D - C ))。然后,代替m,将 ( X -A )/( B - A ) 得到Y = C +((( X - A )/( B - A ))*( D - C ))。这是一个不错的地图功能,但可以简化。取 ( D - C ) 部分,并将其放在被除数内,得到Y = C +((( X - A )*( D - C ))/( B - A ))。这给了我们另一个可以简化的部分, ( X - A )*( D- C ),相当于 ( X * D )-( X * C )-( A * D )+( A * C )。弹出它,你得到Y = C +((( X * D )-( X * C )-( A * D )+( A * C ))/( B - A ))。您需要做的下一件事是添加 + C位。为此,您将C乘以( B - A) 得到 (( B * C )-( A * C )),并将其移入被除数中得到Y =((( X * D )-( X * C )-( A * D )+( A * C )+( B * C )-( A * C ))/( B - A ))。这是多余的,包含一个 +( A * C ) 和一个 -( A * C ),它们相互抵消。删除它们,您将获得以下最终结果:Y =(( X * D )-( X * C )-( A * D )+( B * C ))/( B - A )
TL;DR:标准映射函数Y = C +((( X - A )/( B - A ))*( D - C )) 可以简化为Y =(( X * D )-( X * C )-( A * D )+( B * C ))/( B - A )
如果您的范围从 [a 到 b] 并且您想将其映射到 [c 到 d] 中,其中 x 是您要映射的值,请使用此公式(线性映射)
double R = (d-c)/(b-a)
double y = c+(x*R)+R
return(y)
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);
当然,检查除以零。