数学-映射数字


Answers:


211

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

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

尽管您的问题有点模棱两可,但这应该可以为您提供所需的内容,因为您还可以反向绘制区间。只要当心被零除,就可以了。


16
为了清楚起见,我喜欢new_value =(old_value-old_bottom)/(old_top-old_bottom)*(new_top-new_bottom)+ new_bottom;
frottter

1
这个公式在某处有推导吗?
shaveenk

@shaveenk应该是一条线的方程,其中Y=f(X)=m*X+b,其中m和b是由以下两个约束方程同时确定的,这些方程由将X和Y的值替换为所需的端点C=m*A+bD=m*B+b
得出

最后,我还需要X=A+(A-B)*t证明该方法与Peter的方法相同。t本质上是X的无量纲。(t=(X-A)/(A-B)
克里斯·基亚森

为了反转方向,公式为((XA)/(AB)*(CD))* -1 + D
Corey Levinson

21

除以得到两个范围的大小之间的比率,然后减去初始范围的起始值,再乘以该比率,然后加上第二个范围的起始值。换一种说法,

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

这样可以将第二个范围内的数字从第一个范围平均分布。


这行不通。我的范围是10亿到9999999999并且这些数字可以是从1到999999999
Dejell

@Odelya当然可以。这是一个足够简单的数学转换。您只需要使用足够大的数字类型(bignum或类似数字)即可。对于32位整数,您的数字实在太大了,但是例如64位整数就可以使用。
Konrad Rudolph

它们的类型为double。双R =(20-10)/(6-2); y =(X-2)* R + 10;
Dejell

@Odelya但是同样的问题。您应该阅读浮点精度。实际上,这是必读的:每位计算机科学家都应了解的浮点运算法则-如果您需要具有如此大数字的浮点类型,则可能必须使用任意精度的数字类型
Konrad Rudolph

您能推荐我可以做到的Java类型吗?
Dejell

7

最好在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;
}

我将这段代码放在这里,以供将来参考,可能对某人有帮助。


4

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


这个答案如何?
shinzou

这是该问题的应用示例。许多人在CS入门课中都遇到了这个简单的问题,并不认为该解决方案可以推广到其他问题。我试图将上下文添加到原始问题。最初的问题已经得到了充分的回答。
地铁

1

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

伪:

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

如何处理舍入取决于您。


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);

当然要进行除以零的检查。




0

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

reverseX = (B-A)*(Y-C)/(D-C) + A
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.