2012-02-28 5 views

Odpowiedz

4

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.

1

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; 
} 
Powiązane problemy