我有一个问题,希望你能给我点帮助。如果我有一些在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
是一个能起作用的映射。
a * (0.5) + b = 0
和a * 1 + b = 1
。将第一个方程乘以2后,我们得到两个方程a + 2 * b = 0
和a * 1 + b = 1
。由于两个方程中a
的系数相等,我们可以从第二个方程中减去第一个方程,得到-b = 1
。 - jason将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]
将范围缩放,使其长度为新范围的长度D-C。 (乘以D-C):
[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)
着眼于非线性范围也是很有趣的。您可以采取相同的步骤,但需要额外一步将线性范围转换为非线性范围。
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)
× 2 − 1
这个应该就可以了。
您可以在数学计算中使用clamp或saturate函数,以确保最终值在0-1之间。有些人会在最后一步使用saturate函数,但我也见过在计算过程中使用的情况。