在我的直觉中,甚至经过一番思考之后,如果我想将一个规范化的浮点值转换回定点数,我会将其乘以定点格式能够容纳的最大值。所以乘以 255 或 65535,或其他什么。然而在某些情况下,我看到一些人或代码坚持认为正确的方法是乘以 255 - 1 或 65535 - 1。我不知道为什么会这样或为什么应该这样。这是为了处理溢出吗?我不知道如果将 1.0f * 255 相乘会发生什么不好的事情。即使 1.0f 不能在 IEEE 754 中完美表示并且乘法得出 255.0001,那么当将其转换为整数时它仍然为 255,没有溢出。
编辑:抱歉,我的问题中有两个错误。我的意思是 2 ^ bit_width - 1,而不是 bit_width ^ 2 - 1。这大概是正确的,因此对于 8 位整数,您需要乘以 255,对于 16 位整数,您需要乘以 65535。我的问题是,我很确定我见过乘以 255 - 1(即 254)的代码。有什么理由乘以 254 而不是 255?
您不太可能看到任何代码乘以
BIT_WIDTH ^ 2 MINUS 1
。例如,对于宽度为 16 的情况,这将乘以 16 2 −1 = 256−1 = 255,而 16 位无符号整数的最大值是 65,535。您更有可能看到代码乘以2 ^ BIT_WDITH - 1
,结果为 65,535。考虑一个n位无符号整数格式。其值范围从 0 到 2 n −1。将其映射到浮点区间 [0, 1] 的人可能会选择映射 f: x ➝ x / (2 n −1),因为它将 0 映射到 0,将 2 n −1 映射到 1,并将 0 到 2 n −1之间的每个值映射到 0 到 1 之间的值。
一旦做出选择,逆映射为 f −1 : y ➝ y •(2 n −1)。
我看不出这有什么道理。请给我们看看那些人的话或那段代码的文本。
如果反向映射为y ➝ y •(2 n −2),则正向映射为x ➝ x / (2 n −2)。对于n = 8,这会将 255 映射到 255/254 = 1.045…,这不在通常使用的归一化区间 [0, 1] 内。
这可能有意义的一种方式是,如果定点格式保留值 2 n −1 来表示某些异常情况(例如发生错误或数据丢失),则其数值间隔为 [0, 2 n −2]。在这种情况下,映射将是x ➝ x / ( y ➝ y •(2 n −2) 和y ➝ y •(2 n −2)。