.NET .NET ma wbudowaną metodę obliczania ULP danego double lub float?Obliczyć jednostkę w ostatnim miejscu (ULP) dla podwójnych
Jeśli nie, jaki jest najskuteczniejszy sposób?
.NET .NET ma wbudowaną metodę obliczania ULP danego double lub float?Obliczyć jednostkę w ostatnim miejscu (ULP) dla podwójnych
Jeśli nie, jaki jest najskuteczniejszy sposób?
Wygląda na to, że funkcja jest dość trywialna; ten opiera się na Pseudokod w przyjętym odpowiedzi na pytanie połączonych vulkanino:
double value = whatever;
long bits = BitConverter.DoubleToInt64Bits(value);
double nextValue = BitConverter.Int64BitsToDouble(bits + 1);
double result = nextValue - value;
Dla pływaków, trzeba by dostarczyć własną implementację SingleToInt32Bits
i Int32BitsToSingle
, ponieważ BitConverter nie posiada tych funkcji.
This page pokazuje specjalne przypadki w implementacji funkcji java; ich obsługa powinna być również dość banalna.
phoog odpowiedź jest dobra, ale ma słabości z liczbami ujemnymi, max_double, infinity i NaN.
phoog_ULP (dodatnie x) -> dodatnia liczba. Dobry.
phoog_ULP (ujemny x) -> liczba ujemna. Oczekiwałbym dodatniej liczby.
Aby rozwiązać ten problem polecam zamiast:
long bits = BitConverter.DoubleToInt64Bits(value) & 0x7FFFFFFFFFFFFFFFL;
poniżej są przypadki brzegowe, które wymagają uchwały należy dbać ...
phoog_ULP (x = +/- Max_double 1,797 ... e + 308) powraca nieskończony wynik. (+1.996 ... e + 292) spodziewane.
phoog_ULP (x = +/- Infinity) daje wynik NaN. Oczekiwano nieskończoności.
phoog_ULP (x = +/- NaN) może nieoczekiwanie zmienić się z sNan na qNaN. Nie oczekiwano żadnej zmiany. Można argumentować w dowolny sposób, czy znak powinien w tym przypadku zostać +.
Aby rozwiązać te problemy, widzę tylko krótką serię brutalnych testów(), aby je uwzględnić, możliwe w przypadku "bitów" dla celów praktycznych. Przykład:
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 == 0x7FEFFFFFFFFFFFFL) { // if x == max_double (notice the _E_)
return BitConverter.Int64BitsToDouble(bits) - BitConverter.Int64BitsToDouble(bits - 1);
}
double nextValue = BitConverter.Int64BitsToDouble(bits + 1);
double result = nextValue - value;
}
szczęśliwy czytanie: http://stackoverflow.com/questions/1668183/find-min-max-of-a-float-double-that-has-the-same-internal-representation – vulkanino