我有点被困在这里,我想这是一个脑筋急转弯。如果我的数字在0.5到1之间,我怎样才能将其标准化为0到1?
感谢您提供任何帮助,也许我因为过去24小时工作而感到有点慢O_O
答案 0 :(得分: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
是一个可以解决问题的地图。
答案 1 :(得分:31)
减去0.5(给你一个0到0.5的新范围),然后乘以2.
double normalize( double x )
{
// I'll leave range validation up to you
return (x - 0.5) * 2;
}
答案 2 :(得分:24)
添加另一个通用答案。
如果要将线性范围[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)
看一下非线性范围也很有趣。您可以采取相同的步骤,但需要额外的步骤将线性范围转换为非线性范围。
答案 3 :(得分:15)
×2 - 1
应该做的伎俩
答案 4 :(得分: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)
答案 5 :(得分:0)
您可以在数学中始终使用钳制或饱和来确保您的最终值在0-1之间。有些人在最后饱和,但我也看到它在计算过程中完成了。