将一个连续数据范围非线性地映射到另一个

时间:2014-09-11 03:33:08

标签: algorithm math mapping

对于模糊的标题感到抱歉。我不确定如何简明扼要地说出我要问的内容。这是一个数学/算法问题,而不是编程问题。

在我正在开发的应用中,我们的值可以在0到预定的最大值之间波动(在测试中它通常在100左右徘徊,所以让我们说100 )。这个数据范围是连续的,这意味着存在无限多个可能的值 - 只要它在0到100之间,它就是可能的。

现在,从此返回的任何值都映射到一个也是连续的不同范围 - 从1000到200.因此,如果第一个集合中的值为100,我将其映射到200,如果来自第一个设置为0,它被映射到1000.当然,介于两者之间的一切。这就是代码的样子:

-(float)mapToRange:(float)val withMax:(float)maxVal{
    // Establish range constants.
    const int upperBound = 1000;
    const int lowerBound = 200;
    const int bandwidth = upperBound - lowerBound;

    // Make sure we don't go above the calibrated maximum.
    if(val > maxVal)
        val = maxVal;

    // Scale the original value to our new boundaries.
    float scaled = val/maxVal;
    float ret = upperBound - scaled*bandwidth;

    return ret;
}

现在,我想要做的是使较高的原始值​​(接近100)以较大的增量增加而不是较低的原始值(接近0)。这意味着如果我以稳定的速率慢慢地从100开始减少到0,那么从200开始的新值最初会快速向1000移动,但是越接近1000就越小。这样做的最佳方法是什么? ?

1 个答案:

答案 0 :(得分:1)

您的值scaled基本上是0-100范围内显示的0-1值,因此可以使用它。尝试将此值提高到整数幂,结果将在1附近快速增加,在0附近变慢。功率越高,效果越大。如下所示:

float scaled = val/maxVal;
float bent = scaled*scaled*scaled*scaled;  // or however you want to write x^4
float ret = upperBound - bent*bandwidth;

以下是这个想法的草图: enter image description here

即,范围A to B映射到较小的范围a to b,而范围C to D映射到较大的范围c to d。多项式的幂越大,曲线弯曲到右下角的次数越多。

使用01范围的优势在于,当x^n=xx 01时,端点保持固定{{1}}但是,当然,这并不是必要的,因为通过适当的移动和缩放可以补偿任何事情。

另请注意,此地图不是对称的(尽管我的绘图类似于这种方式),但可以选择对称曲线。如果您想曲线弯曲另一种方式,请选择小于1的功率。