数学 - 映射数字
如何将 a 和 b 之间的数字线性映射到 c 和 d 之间。
也就是说,我希望 2 到 6 之间的数字映射到 10 到 20 之间的数字......但我需要广义的情况。
我的脑子炸了。
How do I map numbers, linearly, between a and b to go between c and d.
That is, I want numbers between 2 and 6 to map to numbers between 10 and 20... but I need the generalized case.
My brain is fried.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
当然,还有除以零的检查。
With checks on divide by zero, of course.
其中 X 是从 A-B 映射到 C-D 的数字,Y 是结果:
取线性插值公式 lerp(a,b,m)=a+(m *(b-a)),并用 C 和 D 代替 a 和 b 得到 Y=C+(m*(D -C))。 然后,用 (X-A)/(B-A< 代替 m /strong>) 得到 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)
Where X is the number to map from A-B to C-D, and Y is the result:
Take the linear interpolation formula, lerp(a,b,m)=a+(m*(b-a)), and put C and D in place of a and b to get Y=C+(m*(D-C)). Then, in place of m, put (X-A)/(B-A) to get Y=C+(((X-A)/(B-A))*(D-C)). This is an okay map function, but it can be simplified. Take the (D-C) piece, and put it inside the dividend to get Y=C+(((X-A)*(D-C))/(B-A)). This gives us another piece we can simplify, (X-A)*(D-C), which equates to (X*D)-(X*C)-(A*D)+(A*C). Pop that in, and you get Y=C+(((X*D)-(X*C)-(A*D)+(A*C))/(B-A)). The next thing you need to do is add in the +C bit. To do that, you multiply C by (B-A) to get ((B*C)-(A*C)), and move it into the dividend to get Y=(((X*D)-(X*C)-(A*D)+(A*C)+(B*C)-(A*C))/(B-A)). This is redundant, containing both a +(A*C) and a -(A*C), which cancel each other out. Remove them, and you get a final result of: Y=((X*D)-(X*C)-(A*D)+(B*C))/(B-A)
TL;DR: The standard map function, Y=C+(((X-A)/(B-A))*(D-C)), can be simplified down to Y=((X*D)-(X*C)-(A*D)+(B*C))/(B-A)
如果您的范围从 [a 到 b] 并且您想要将其映射到 [c 到 d],其中 x 是您要映射的值
使用这个公式(线性映射)
if your range from [a to b] and you want to map it in [c to d] where x is the value you want to map
use this formula (linear mapping)
第一个范围上的每个单位间隔占用第二个范围上的 (dc)/(ba)“空间”。
Pseudo:
如何处理舍入取决于您。
Each unit interval on the first range takes up (d-c)/(b-a) "space" on the second range.
Pseudo:
How you handle the rounding is up to you.
https://rosettacode.org/wiki/Map_range
https://rosettacode.org/wiki/Map_range
除了 @PeterAllenWebb 答案之外,如果您想反转结果,请使用以下命令:
In addition to @PeterAllenWebb answer, if you would like to reverse back the result use the following:
顺便说一句,这与经典的摄氏度转换为华氏度的问题相同,您想要映射等于 0 - 100 (C) 到 32 - 212 (F) 的数字范围。
As an aside, this is the same problem as the classic convert celcius to farenheit where you want to map a number range that equates 0 - 100 (C) to 32 - 212 (F).
最好在
java.lang.Math
类中拥有此功能,因为这是一个广泛需要的功能,并且在其他语言中也可用。这是一个简单的实现:
我将此代码放在这里作为未来自己的参考,可能会对某人有所帮助。
It would be nice to have this functionality in the
java.lang.Math
class, as this is such a widely required function and is available in other languages.Here is a simple implementation:
I am putting this code here as a reference for future myself and may be it will help someone.
除以得到两个范围大小之间的比率,然后减去初始范围的起始值,乘以该比率并加上第二个范围的起始值。 换句话说,
这将第一个范围中的数字均匀分布在第二个范围中。
Divide to get the ratio between the sizes of the two ranges, then subtract the starting value of your inital range, multiply by the ratio and add the starting value of your second range. In other words,
This evenly spreads the numbers from the first range in the second range.
如果你的数字 X 落在 A 和 B 之间,并且你希望 Y 落在 C 和 D 之间,你可以应用以下线性变换:
这应该给你你想要的,尽管你的问题有点模棱两可,因为你也可以沿相反方向映射间隔。 只要注意被零除就应该没问题。
If your number X falls between A and B, and you would like Y to fall between C and D, you can apply the following linear transform:
That should give you what you want, although your question is a little ambiguous, since you could also map the interval in the reverse direction. Just watch out for division by zero and you should be OK.