我有点卡在这里,我想这有点脑筋急转弯。如果我的数字在 0.5 到 1 之间,如何将其标准化为 0 到 1 之间?
感谢您的帮助,也许我只是有点慢,因为我过去 24 小时一直在工作 O_O
其他人为您提供了公式,但没有为您提供工作。这是您处理此类问题的方法。你可能会发现这比仅仅知道答案更有价值。
为了映射[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
是一张可以解决问题的地图。
减去 0.5(给你一个 0 - 0.5 的新范围)然后乘以 2。
double normalize( double x )
{
// I'll leave range validation up to you
return (x - 0.5) * 2;
}
添加另一个通用答案。
如果要将线性范围 [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)
看看非线性范围也很有趣。您可以采取相同的步骤,但需要额外的步骤将线性范围转换为非线性范围。
× 2 − 1
应该做的伎俩
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)
你总是可以在你的数学中使用钳位或饱和来确保你的最终值在 0-1 之间。有些在最后饱和,但我也看到它在计算过程中完成。