math映射数字

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

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

我的大脑被炸。

如果你的数字X落在A和B之间,而你希望Y落在C和D之间,你可以应用下面的线性变换:

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

这应该给你你想要的,虽然你的问题是有点含糊不清,因为你也可以映射间隔在相反的方向。 只要小心零分,你应该没问题。

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

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

这将从第二个范围的第一个范围中均匀分布数字。

顺便说一下,这与经典的转换模式相同,就是想要映射一个等于0 – 100(C)到32 – 212(F)的数字范围。

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

伪:

 var interval = (dc)/(ba) 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); 

当然,用零除检查。

java.lang.Math类中有这个function是很好的,因为这是一个广泛需要的function,并且在其他语言中是可用的。 这是一个简单的实现:

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

我把这个代码放在这里作为未来的参考,可能会帮助别人。

除了@PeterAllenWebb的回答,如果你想扭转结果使用以下内容:

 reverseX = (BA)*(YC)/(DC) + A