计算最后一个单位(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;
对于浮点数,您需要提供自己的Int32BitsToSingle
和Int32BitsToSingle
,因为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); }