【问题标题】:Normalizing from [0.5 - 1] to [0 - 1]从 [0.5 - 1] 规范化到 [0 - 1]
【发布时间】:2010-12-01 01:53:15
【问题描述】:

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

感谢您的帮助,也许我在过去的 24 小时内一直在工作,所以我的速度有点慢 O_O

【问题讨论】:

  • 我认为 + 投票完全针对“过去 24 小时连续工作”:)

标签: c++ math hlsl normalize


【解决方案1】:

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

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

方法一:端点映射到端点并保留顺序的要求意味着0.5映射到01映射到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)乘以-2?
  • @RobertL:要求解具有两个未知数的两个方程的线性系统,最简单的方法是将系统转换为等效系统,其中一个未知数的系数在两个方程中相等。所以这里我们有两个方程a * (0.5) + b = 0a * 1 + b = 1。将第一个方程乘以2 后,我们得到两个方程a + 2 * b = 0a * 1 + b = 1。由于a 上的系数在两个方程中相等,我们可以从第二个方程中减去第一个方程得到-b = 1
【解决方案2】:

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

double normalize( double x )
{
    // I'll leave range validation up to you
    return (x - 0.5) * 2;
}

【讨论】:

    【解决方案3】:

    添加另一个通用答案。

    如果要将线性范围 [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)
    

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

    【讨论】:

    • 为了适应非线性范围,您需要做什么?我想将 -1..1 的范围转换为 -.25..1,其中 -.25..0..1 = -1..0..1 (所以 -0.25..0 是-1..0)。
    【解决方案4】:

    × 2 − 1

    应该做的伎俩

    【讨论】:

    • 这是我解决的解决方案的数学部分,而不是与语言相关的部分
    【解决方案5】:

    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)
    

    【讨论】:

    • 我喜欢你概括你的答案的方式。我使用您的语法在 Python 中执行此操作。 +1
    【解决方案6】:

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

    【讨论】: