27

我有点卡在这里,我想这有点脑筋急转弯。如果我的数字在 0.5 到 1 之间,如何将其标准化为 0 到 1 之间?

感谢您的帮助,也许我只是有点慢,因为我过去 24 小时一直在工作 O_O

4

6 回答 6

65

其他人为您提供了公式,但没有为您提供工作。这是您处理此类问题的方法。你可能会发现这比仅仅知道答案更有价值。

为了映射[0.5, 1]到,[0, 1]我们将寻求形式的线性映射x -> ax + b。我们将要求端点映射到端点并保留该顺序。

方法一:端点映射到端点并保留顺序的要求意味着0.5映射到0并被1映射到1

a * (0.5) + b = 0 (1)
a * 1 + b = 1     (2)

(1)这是一个线性方程组的联立系统,可以通过将方程乘以方程-2并将方程添加到方程(1)来求解(2)。这样做后,我们得到b = -1并将其代入方程(2),我们得到a = 2。因此,地图x -> 2x - 1将起到作用。

方法二:通过两点的直线的(x1, y1)斜率(x2, y2)

(y2 - y1) / (x2 - x1).

在这里,我们将使用点(0.5, 0)(1, 1)满足端点映射到端点的要求,并且映射是保序的。因此斜率为

m = (1 - 0) / (1 - 0.5) = 1 / 0.5 = 2.

我们有它(1, 1)是线上的一个点,因此通过线方程的点斜率形式,我们有

y - 1 = 2 * (x - 1) = 2x - 2

以便

y = 2x - 1.

我们再次看到这x -> 2x - 1是一张可以解决问题的地图。

于 2009-09-24T13:24:21.827 回答
31

减去 0.5(给你一个 0 - 0.5 的新范围)然后乘以 2。

double normalize( double x )
{
    // I'll leave range validation up to you
    return (x - 0.5) * 2;
}
于 2009-09-24T12:30:33.433 回答
24

添加另一个通用答案。

如果要将线性范围 [A..B] 映射到 [C..D],可以应用以下步骤:

移动范围,使下限为 0。(从两个边界中减去 A:

[A..B] -> [0..B-A]

缩放范围,使其为 [0..1]。(除以上限):

[0..B-A] -> [0..1]

缩放范围,使其具有新范围的长度,即 DC。(乘以 DC):

[0..1] ->  [0..D-C]

移动范围,使下限为 C。(将 C 添加到边界):

[0..D-C] -> [C..D]

将其结合到一个公式中,我们得到:

       (D-C)*(X-A)
X' =   -----------  + C
          (B-A)

在你的情况下, A=0.5, B=1, C=0, D=1 你得到:

       (X-0.5)
X' =   ------- = 2X-1
        (0.5)

请注意,如果您必须将大量 X 转换为 X',您可以将公式更改为:

       (D-C)         C*B - A*D
X' =   ----- * X  +  ---------  
       (B-A)           (B-A)

看看非线性范围也很有趣。您可以采取相同的步骤,但需要额外的步骤将线性范围转换为非线性范围。

于 2009-09-25T13:23:20.287 回答
15

× 2 − 1

应该做的伎俩

于 2009-09-24T12:29:02.193 回答
14

Lazyweb 回答:要将值x从转换[minimum..maximum][floor..ceil]

一般情况:

normalized_x = ((ceil - floor) * (x - minimum))/(maximum - minimum) + floor

标准化为 [0..255]:

normalized_x = (255 * (x - minimum))/(maximum - minimum)

标准化为 [0..1]:

normalized_x = (x - minimum)/(maximum - minimum)
于 2013-06-10T17:41:14.480 回答
0

你总是可以在你的数学中使用钳位或饱和来确保你的最终值在 0-1 之间。有些在最后饱和,但我也看到它在计算过程中完成。

于 2014-01-13T23:03:50.490 回答