112

如何在 a 和 b 之间线性映射数字以在 c 和 d 之间移动。

也就是说,我希望 2 到 6 之间的数字映射到 10 到 20 之间的数字......但我需要广义的情况。

我的大脑被炸了。

4

10 回答 10

231

如果您的数字 X 介于 A 和 B 之间,并且您希望 Y 介于 C 和 D 之间,则可以应用以下线性变换:

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

这应该给你你想要的,虽然你的问题有点模棱两可,因为你也可以在相反的方向上映射间隔。只要注意被零除,你应该没问题。

于 2008-12-05T21:28:03.523 回答
23

除以得到两个范围大小之间的比率,然后减去初始范围的起始值,乘以比率并添加第二个范围的起始值。换句话说,

R = (20 - 10) / (6 - 2)
y = (x - 2) * R + 10

这将第一个范围的数字均匀地分布在第二个范围内。

于 2008-12-05T21:28:01.353 回答
9

在课堂上拥有这个功能会很好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;
}

我把这段代码放在这里作为自己未来的参考,可能会对某人有所帮助。

于 2016-12-11T15:56:39.460 回答
3

顺便说一句,这与经典的将摄氏度转换为华氏度的问题相同,您想要映射一个等于 0 - 100 (C) 到 32 - 212 (F) 的数字范围。

于 2008-12-05T23:57:35.763 回答
3

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)
于 2020-03-17T22:23:27.247 回答
2

除了@PeterAllenWebb 答案,如果您想反转结果,请使用以下命令:

reverseX = (B-A)*(Y-C)/(D-C) + A
于 2013-02-19T10:57:19.977 回答
1

第一个范围上的每个单位间隔占用第二个范围上的 (dc)/(ba)“空间”。

伪:

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

如何处理舍入取决于您。

于 2008-12-05T21:31:32.690 回答
1

其中X是从A - B映射到C - D的数,Y是结果:采用线性插值公式,lerp( a , b , m )= a +( m *( b - a )),并且用CD代替ab得到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 )

于 2020-10-13T16:03:03.190 回答
1

如果您的范围从 [a 到 b] 并且您想将其映射到 [c 到 d] 中,其中 x 是您要映射的值,请使用此公式(线性映射)

double R = (d-c)/(b-a)
double y = c+(x*R)+R
return(y)
于 2019-01-09T07:51:21.747 回答
0
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);

当然,检查除以零。

于 2008-12-05T23:28:22.063 回答