数学从来不是我在学校的强项
int input_start = 0; // The lowest number of the range input.
int input_end = 254; // The largest number of the range input.
int output_start = 500; // The lowest number of the range output.
int output_end = 5500; // The largest number of the range output.
int input = 127; // Input value.
int output = 0;
如何将输入值转换为该范围的相应输出值?
例如,输入值“0”等于输出值“500”,输入值“254”等于输出值“5500”。如果输入值是50或101,我不知道如何计算输出值。
我相信这很简单,我现在无法思考:)
编辑:我只需要整数,没有分数或任何东西。
6条答案
按热度按时间jhiyze9q1#
让我们忘掉数学,试着用直觉来解决这个问题。
首先,如果我们想把范围[
0
,x
]中的输入数字Map到输出范围[0
,y
],我们只需要适当地缩放。0变成0,x
变成y
,数字t
变成(y/x)*t
。所以,让我们把你的问题简化为上面这个简单的问题。
输入范围[
input_start
,input_end
]包含input_end - input_start + 1
个数字,因此它等效于范围[0
,r
],其中r = input_end - input_start
。同样,输出范围等于[
0
,R
],其中R = output_end - output_start
。输入
input
等于x = input - input_start
,第一段中的值将转换为y = (R/r)*x
,然后,我们可以通过添加output_start
将y
值转换回原始输出范围:output = output_start + y
.这给我们:
或者,换一种方式:
现在,这是C语言,C语言中的除法运算会被截断,你应该尝试用浮点运算来得到一个更准确的答案:
如果想要更准确,你可以在最后一步进行舍入而不是截断,你可以通过写一个简单的
round
函数来实现:然后:
ryevplcw2#
Arduino内置了map。
示例:
在该页面上还提供了以下实现:
nsc4cvqm3#
其公式为
f(x)=(x -输入_开始)/(输入_结束-输入_开始)*(输出_结束-输出_开始)+输出_开始
我会在这里挂起这个帖子:https://betterexplained.com/articles/rethinking-arithmetic-a-visual-guide/,因为它帮助我很大,当试图想出这个直观的。一旦你明白了帖子是什么,它是微不足道的想出这些公式自己。注意,我曾经挣扎与这样的问题,以及。(我没有从属关系-只是发现它非常有用)
假设你有一个值域
[input_start..input_end]
,让我们先把它归一化,0是input_start
,1是input_end
。这是一个简单的技巧,可以使问题变得更容易。怎么做呢,我们要把所有的东西都左移一个input_start的量,这样如果input,x,正好是
input_start
,它应该给予零.假设
f(x)
是执行转换的函数。让我们试试看:
适用于
input_start
。在这一点上,它还不适用于
input_end
,因为我们还没有缩放它。让我们按范围的长度缩小它,然后我们将最大值(input_end)Map为1。
好的,让我们用
input_end
来尝试一下。f
(input_end) = (input_end - input_start) / (input_end - input_start) = 1
太棒了,好像有用。
好的,下一步,我们实际上将把它缩放到输出范围,这就像乘以输出范围的实际长度一样简单,如下所示:
现在,实际上,我们差不多完成了,我们只需要将其向右移动,以便0从output_start开始。
让我们快速地给予一下。
你会看到方程的第一部分几乎都乘以了零,这样就抵消了所有的项,得到
让我们也试试
input_end
。这反过来又会变成:
正如您所看到的,它现在似乎已正确Map。
cigdeys34#
这里的关键点是在正确的地方做整数除法(包括四舍五入)。到目前为止,没有一个答案正确地做了括号。下面是正确的方法:
yrefmtwq5#
保证将任何范围Map到任何范围
我编写了这个方法,它严格遵循将数字从一个范围Map到另一个范围的代数公式。计算使用双精度来保持精度,然后在最后,它将返回一个Double,其中包含您在方法参数中指定的小数位数。
没有必要将范围的下限和上限命名为low或high,因为无论范围的一端低于或高于另一端都没有区别,该方法仍将正确Map数字。
例如,如果您将任何范围指定为[-100至300]或[300至-100],则不会有任何区别,重新Map仍然会准确地输出。
以下是在代码中使用方法的方式:
下面是如何使用该方法的示例:
来源范围:-400至800
目的地范围:一万至三千五百
要重新Map的编号:250
如果你需要一个整数返回,只需要传入0个小数位,然后像这样将结果转换为int:
或者,您可以声明该方法返回一个int,并删除decimalPrecision参数,然后将最后两行更改为:
在OP问题中,他们会像这样使用函数:
方法是这样的:
在我的用例中,我需要淡出JavaFX控件的不透明度,但由于不透明度是0到1之间的数字,我只是使用该方法将范围1到100(基于将int从0递增到100的for循环)重新Map到范围0到1,效果非常好。
虽然我现在知道我可以通过将增量从1更改为.01来创建循环,如下所示:
我只是为任何可能正在做类似于我正在做的事情的人指出这一点。这个方法按照描述的那样完美地工作。
:—)
kb5ga3dv6#
它的作用是按比例找出输入在输入范围内的”深度“,然后将该比例应用于输出范围的大小,以绝对值的形式找出输出应该在输出范围内的深度,然后将输出范围的起点相加,得到实际的输出数。