安全反转浮点计算

Safely invert floating point calculation

我想知道反转这个计算的正确方法是什么:

float x = a * 25.0f + b; // where a and b are integers and b is in [0-25[

如何避免可能出现的浮点舍入错误。答案很明显,即使 x 有一些错误,所以应该可以实现。

尝试使用模运算,即整数除法/和余数%:

int a = ((int) (x + 0.5f)) / 25; 
int b = ((int) (x + 0.5f)) % 25; 

如果 x 可能有 舍入错误,例如x = 53.999997 而不是 54 然后 舍入 到最接近的整数:(int) (x + 0.5f)。请注意 x 应该 足够小 才能转换为 intx = 1e30f 肯定会失败。

对于你给的a的范围,你不能安全的取回b。

对于a=10^6,你需要20bits。如果乘以 25,则还需要 5 位。因此,对于 a 的极值,您需要 25 位有效数字来表示 x。 IEEE 754 单精度浮点数只提供 24。这意味着 x 可能会丢失最低有效位。你得到的不是真实值 x,而是 x+/-1。

但是您可以访问更多信息:

  • 如果 x<2^24,那么你知道你可以通过朴素算法检索 b 和 a
  • 如果 x >= 2^24 且尾数为奇数 ((int)(x))%4 == 2,则您知道没有进行舍入。实际上,取消最后一位是精确绑定的情况,即使在 IEEE 754 默认舍入模式下也会导致舍入到最接近的值。
  • 仅在 x >= 2^24 且尾数为偶数的情况下,您无法得出结论,并且 {a,b} 对有 3 个可能的值。

结论:你应该在这里使用双精度