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