.NET是否有内置方法来计算给定double或float的ULP?
如果没有,最有效的方法是什么?
答案 0 :(得分:6)
看起来这个功能非常简单;这是基于vulkanino关联的问题的接受答案中的伪代码:
double value = whatever;
long bits = BitConverter.DoubleToInt64Bits(value);
double nextValue = BitConverter.Int64BitsToDouble(bits + 1);
double result = nextValue - value;
对于浮点数,您需要提供自己的SingleToInt32Bits
和Int32BitsToSingle
实现,因为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);
}