Jaka jest największa liczba całkowita „no-floating”, która może być przechowywana w podwójnym typie IEEE 754 bez utraty precyzji?
Jaka jest największa liczba całkowita „no-floating”, która może być przechowywana w podwójnym typie IEEE 754 bez utraty precyzji?
Odpowiedzi:
Największa / największa liczba całkowita, którą można zapisać w podwójnej pamięci bez utraty precyzji, jest taka sama, jak największa możliwa wartość podwójnej. To znaczy, DBL_MAX
czyli około 1,8 × 10 308 (jeśli twoje podwójne to 64-bitowe podwójne IEEE 754). To jest liczba całkowita. Jest dokładnie reprezentowany. Czego jeszcze chcesz?
Kontynuuj, zapytaj mnie, jaka jest największa liczba całkowita, tak że ona i wszystkie mniejsze liczby całkowite mogą być przechowywane w 64-bitowych podwójnych wersjach IEEE bez utraty precyzji. 64-bitowe podwójne IEEE ma 52 bity mantysy, więc myślę, że to 2 53 :
Lub inny sposób patrzenia na to: po usunięciu odchylenia wykładnika i zignorowaniu bitu znaku jako nieistotnego dla pytania, wartość przechowywana przez podwójność jest potęgą 2, plus 52-bitowa liczba całkowita pomnożona przez 2 wykładnik - 52 . Tak więc z wykładnikiem 52 możesz zapisać wszystkie wartości od 2 52 do 2 53 - 1. Następnie z wykładnikiem 53 następną liczbą, którą możesz zapisać po 2 53, jest 2 53 + 1 × 2 53 - 52 . Tak więc utrata precyzji występuje najpierw przy 2 53 + 1.
9007199254740992 (to 9 007,199,254,740,992) bez gwarancji :)
Program
#include <math.h>
#include <stdio.h>
int main(void) {
double dbl = 0; /* I started with 9007199254000000, a little less than 2^53 */
while (dbl + 1 != dbl) dbl++;
printf("%.0f\n", dbl - 1);
printf("%.0f\n", dbl);
printf("%.0f\n", dbl + 1);
return 0;
}
Wynik
9007199254740991 9007199254740992 9007199254740992
double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);
daje ten sam wynik
while (dbl == --dbl)
zapętla się na zawsze lub wcale. :) (w tym przypadku wcale nie, ponieważ jest to 2 ^ N). Musisz podejść do tego od dołu. Rzeczywiście spowoduje to również jeden wynik mniejszy niż oczekiwany (ponieważ to sprawdzenie w pętli while zmniejsza dbl). I to zależy od kolejności wykonania, jeśli zmniejszenie jest wykonywane przed lub po ocenie lewej strony (co jest nieokreślone, o ile mi wiadomo). Jeśli jest to pierwsze, zawsze będzie to prawdą i zapętli się na zawsze.
while (dbl + 1 != dbl) dbl++;
w tym, która dbl + 1 != dbl
może ocenić użycie long double
matematyki - rozważ FLT_EVAL_METHOD == 2
. Może to zakończyć się nieskończoną pętlą.
Wikipedia ma to do powiedzenia w tym samym kontekście z linkiem do IEEE 754 :
W typowym systemie komputerowym binarna liczba zmiennoprzecinkowa „podwójnej precyzji” (64-bitowa) ma współczynnik 53 bity (z których jeden jest domyślny), wykładnik 11 bitów i jeden bit znaku.
2 ^ 53 to nieco ponad 9 * 10 ^ 15.
Największa liczba całkowita, która może być reprezentowana w podwójnym standardzie IEEE 754 (64-bit), jest taka sama, jak największa wartość, jaką może reprezentować typ, ponieważ sama ta wartość jest liczbą całkowitą.
Jest to reprezentowane jako 0x7FEFFFFFFFFFFFFF
, które składa się z:
0x7FE
(2046, który reprezentuje 1023 po odjęciu uprzedzenia) zamiast 0x7FF
(2047, co oznacza a NaN
lub nieskończoność).0xFFFFFFFFFFFFF
która wynosi 52 bity wszystkie 1.W systemie binarnym wartością jest domyślna 1, po której następują kolejne 52 z mantysy, a następnie 971 zer (1023 - 52 = 971) z wykładnika.
Dokładna wartość dziesiętna to:
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
To około 1,8 x 10 308 .
Musisz spojrzeć na rozmiar mantysy. 64-bitowa liczba zmiennoprzecinkowa IEEE 754 (która ma 52 bity plus 1 domyślnie) może dokładnie reprezentować liczby całkowite o wartości bezwzględnej mniejszej lub równej 2 ^ 53.
1,7976931348623157 × 10 ^ 308
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
DECIMAL_DIG
z <float.h>
powinien dać przynajmniej rozsądne przybliżenie tego. Ponieważ dotyczy to cyfr dziesiętnych i jest naprawdę przechowywane w formacie binarnym, prawdopodobnie można przechowywać coś nieco większego bez utraty precyzji, ale dokładnie o ile trudno powiedzieć. Przypuszczam, że powinieneś być w stanie to rozgryźć FLT_RADIX
i DBL_MANT_DIG
, ale nie jestem pewien, czy całkowicie ufam wynikowi.
double
odpowiada bezpośrednio określonemu typowi IEEE, ale nie jest to wymagane, a kiedy ta odpowiedź została napisana, pytanie nie wspomniało również o konkretnym typie IEEE.