计算最后一个位置(ULP)的单位为双打

时间:2012-02-28 16:39:05

标签: c# .net floating-point double

.NET是否有内置方法来计算给定double或float的ULP

如果没有,最有效的方法是什么?

2 个答案:

答案 0 :(得分:6)

看起来这个功能非常简单;这是基于vulkanino关联的问题的接受答案中的伪代码:

double value = whatever;
long bits = BitConverter.DoubleToInt64Bits(value);
double nextValue = BitConverter.Int64BitsToDouble(bits + 1);
double result = nextValue - value;

对于浮点数,您需要提供自己的SingleToInt32BitsInt32BitsToSingle实现,因为BitConverter没有这些函数。

This page显示了该函数的java实现中的特殊情况;处理这些也应该是相当微不足道的。

答案 1 :(得分:3)

phoog answer很好,但有负数,max_double,无穷大和NaN的弱点。

phoog_ULP(正x) - >一个正数。好。
phoog_ULP(负x) - >负数。我期待正数 为了解决这个问题,我建议改为:

long bits = BitConverter.DoubleToInt64Bits(value) & 0x7FFFFFFFFFFFFFFFL;

以下是您需要解决的需要解决的边缘案例......

phoog_ULP(x = +/- Max_double 1.797 ... e + 308)返回无限结果。 (+1.996 ... e + 292)预计 phoog_ULP(x = +/- Infinity)导致NaN。 +无限期望。
phoog_ULP(x = +/- NaN)可能会意外地从sNan变为qNaN。没有预期的变化。在这种情况下,如果标志应该变为+,则可以争论任何一种方式。


为了解决这些问题,我只看到一系列简短的野蛮if()测试以适应这些,可以在" bit"权宜之计。示例:

double ulpc(double value) {
  long long bits = BitConverter::DoubleToInt64Bits(value);
  if ((bits & 0x7FF0000000000000L) == 0x7FF0000000000000L) { // if x is not finite
    if (bits & 0x000FFFFFFFFFFFFFL) { // if x is a NaN
      return value;  // I did not force the sign bit here with NaNs.
      } 
    return BitConverter.Int64BitsToDouble(0x7FF0000000000000L); // Positive Infinity;
    }
  bits &= 0x7FFFFFFFFFFFFFFFL; // make positive
  if (bits == 0x7FEFFFFFFFFFFFFFL) { // if x == max_double (notice the _E_)
    return BitConverter.Int64BitsToDouble(bits) - BitConverter.Int64BitsToDouble(bits-1);
  }
  double nextValue = BitConverter.Int64BitsToDouble(bits + 1);
  double result = nextValue - fabs(value);
}