2013-03-26 9 views
5

Jaki jest dokładny zakres (ciągłych) liczb całkowitych, które można wyrazić jako podwójny (czy też unoszący się)? Powód, dla którego pytam, jest taki, ponieważ jestem ciekawy questions such as this one, gdy nastąpi utrata dokładności.Zakres liczb całkowitych, które można dokładnie wyrazić jako zmiennoprzecinkowe/dwójkowe

To

  1. Jaka jest najmniejsza dodatnia m takie, że m+1 nie można precyzyjnie wyrażone jako podwójne (odp. Float)?
  2. Jaka jest największa ujemna liczba całkowita -n taka, że ​​-n-1 nie może być precyzyjnie wyrażona jako podwójna (odpowiednio zmienna)? (Może być taki sam jak powyżej).

Oznacza to, że każda liczba całkowita pomiędzy -n i m ma dokładnie takie reprezentacji zmiennoprzecinkowej. Zasadniczo szukam zakresu [-n, m] dla jednostek pływających i podwójnych.

Ograniczmy zakres do 32-bitowych i 64-bitowych reprezentacji zmiennoprzecinkowych w postaci . Wiem, że float ma 24 bity precyzji, a double ma 53 bity (oba z ukrytym bitem wiodącym), ale ze względu na zawiłości reprezentacji zmiennoprzecinkowej szukam autorytatywnej odpowiedzi na to. Proszę nie machać rękami!

(odpowiedź Ideałem byłoby udowodnić, że wszystkie liczby całkowite od 0 do m są podlegać ekspresji, a m+1 nie jest.)

Odpowiedz

6

Skoro pytasz o typach IEEE zmiennoprzecinkowych, język nie ma znaczenia.

#include <iostream> 
using namespace std; 

int main(){ 

    float f0 = 16777215.; // 2^24 - 1 
    float f1 = 16777216.; // 2^24 
    float f2 = 16777217.; // 2^24 + 1 

    cout << (f0 == f1) << endl; 
    cout << (f1 == f2) << endl; 

    double d0 = 9007199254740991.; // 2^53 - 1 
    double d1 = 9007199254740992.; // 2^53 
    double d2 = 9007199254740993.; // 2^53 + 1 

    cout << (d0 == d1) << endl; 
    cout << (d1 == d2) << endl; 
} 

wyjściowa:

0 
1 
0 
1 

więc limit dla pływaka jest 2^24. Limit podwójny to 2^53. Negatywy są takie same, ponieważ jedyną różnicą jest bit znaku.

+0

Oznaczono tagami z językami, ponieważ nie było ruchu dla innych tagów, których próbowałem. Dziękuję za odpowiedź! –

+0

Kyurem jest martwy w swojej analizie. Ale jeśli chcesz empirycznego rozwiązania, po prostu przetestuj z pętlą for: 'float f = 0; for (;; ++ f) {if (f == (f + 1)) {cout << f; przerwa; }} '. Podobne do podwójnych i negatywnych. –