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

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

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

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

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

对于浮点数,您需要提供自己的Int32BitsToSingleInt32BitsToSingle ,因为BitConverter没有这些function。

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

phoog答案很好,但有负数,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()测试以适应这些,可以在“位”值上进行权宜之计。 例:

 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); }