największa liczba całkowita, którą można zapisać w podwójnym

225

Jaka jest największa liczba całkowita „no-floating”, która może być przechowywana w podwójnym typie IEEE 754 bez utraty precyzji?

Franck Freiburger
źródło

Odpowiedzi:

506

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_MAXczyli 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 :

  • Nie można zapisać 2 53 + 1, ponieważ 1 na początku i 1 na końcu mają między sobą zbyt wiele zer.
  • Można zapisać mniej niż 2 53 , z 52 bitami jawnie zapisanymi w mantysie, a następnie wykładnik daje ci kolejny.
  • 2 53 oczywiście można przechowywać, ponieważ jest to niewielka moc 2.

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.

Steve Jessop
źródło
126
+1 Dobra robota, zauważając, że pytanie tak naprawdę nie znaczyło, co pytający prawdopodobnie zamierzał, i udzielając obu odpowiedzi („technicznie poprawne” i „prawdopodobnie oczekiwane”).
Pascal Cuoq,
62
Lub „zadzierać” i „próbować pomóc”, jak zwykle je nazywam :-)
Steve Jessop
8
Kłaniam się Tony'emu kucykowi i nikomu innemu.
Steve Jessop,
11
Nie masz na myśli „wszystkich mniejszych liczb całkowitych”, masz na myśli wszystkie liczby całkowite o równej lub mniejszej wielkości. Ponieważ istnieje wiele ujemnych liczb całkowitych poniżej 2 ^ 53 i nie można ich dokładnie przedstawić w postaci podwójnej.
Southern Hospitality,
13
Mam na myśli mniejszy i dokładnie to mam na myśli, gdy mówię mniejszy :-) -1 000 000 to mniej niż 1, ale nie jest mniejsze.
Steve Jessop,
77

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
pmg
źródło
7
Zakładając, że będzie „blisko”, ale mniej niż 2 ^ N, wtedy szybszy test double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);daje ten sam wynik
Seph
4
@Sef co do ...? Nie? 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.
falstro
10
Może wskazywać, że 2 ^ 53 = 9 007,199,254,740,992 gdzieś.
Xonatron
1
Trudno się z tym kłócić! Niezły eksperyment
MattM,
Słabość użycia while (dbl + 1 != dbl) dbl++;w tym, która dbl + 1 != dblmoże ocenić użycie long doublematematyki - rozważ FLT_EVAL_METHOD == 2. Może to zakończyć się nieskończoną pętlą.
chux - Przywróć Monikę
25

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.

Carl Smotricz
źródło
@ Steve Jessop mniej więcej tak właśnie mówię. Zetknąłem się również z systemami sprzętowymi, które nie mają FPU, które wciąż muszą być zgodne z IEEE, więc „typowy system” nie pomaga mi, jeśli wrócę tu 8 miesięcy później i potrzebuję tych samych informacji mój mikrokontroler oparty na 68K (zakładając, że nie ma FPU ... nie pamiętam).
San Jacinto,
14
@San Jacinto - „To bezużyteczne” jest zbyt surowe. Odpowiedź jest dość przydatna, po prostu nie tak przydatna, jak w przypadku, gdyby zawierała komentarz, że typowe systemy komputerowe rzeczywiście wykorzystują representencję IEEE 754.
Stephen C. Steel
@ Stephen C. Steel, właściwie masz rację. Zgodnie z moim scenariuszem, wracając do tego w późniejszym czasie i szukając IEEE max, jest to niewiarygodnie dwuznaczne, co to jest „typowy system”, ale odpowiedź nadal jest uzasadniona oprócz tej skargi.
San Jacinto,
20

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:

  • Bit znaku 0 (dodatni) zamiast 1 (ujemny)
  • Maksymalny wykładnik 0x7FE(2046, który reprezentuje 1023 po odjęciu uprzedzenia) zamiast 0x7FF(2047, co oznacza a NaNlub nieskończoność).
  • Maksymalna mantysa, 0xFFFFFFFFFFFFFktó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 .

Simon Biber
źródło
A co z największą wartością, jaką może reprezentować przy wszystkich wartościach między nią a zerem, które mogą być reprezentowane w sposób ciągły?
Aaron Franke
@AaronFranke Pytanie nie dotyczyło ciągłej reprezentacji, ale odpowiedź na to inne pytanie została zawarta w większości innych odpowiedzi tutaj, a nawet błędnie podana jako rzeczywista odpowiedź. Ma 2⁵³ (2 do potęgi 53).
Simon Biber
8

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.

Delfin
źródło
8
Może również dokładnie reprezentować 2 ^ 53 :-)
Steve Jessop
6

1,7976931348623157 × 10 ^ 308

http://en.wikipedia.org/wiki/Double_precision_floating-point_format

Sójka
źródło
2
odpowiedź ta byłaby znacznie lepsza w przypadku cytowania.
San Jacinto,
2
@ Dobrze, jeśli liczba całkowita ma zera po lewej stronie, to jest dokładnie przechowywana.
Wilhelm,
4
@ all downvoters: 1.7976931348623157 × 10 ^ 308 jest dokładną liczbą całkowitą. Czy wszyscy musicie uczestniczyć w lekcjach matematyki naprawczej czy coś takiego?
Dan Molding
6
W dyskusji o tej beznadziejnie zatopionej odpowiedzi sprowadzamy się do semantyki. To prawda, że ​​liczba ta może być dokładnie przedstawiona, a tym samym spełnia literę pytania. Ale wszyscy wiemy, że jest to niewielka wyspa dokładności w oceanie bliskich nieudanych wypadków i większość z nas poprawnie interpolowała pytanie, co oznacza „największą liczbę, powyżej której precyzja idzie w błoto”. Ach, czy to nie cudowne, że CompSci jest nauką ścisłą? :)
Carl Smotricz,
2
@DanMoulding 1.7976931348623157 × 10 ^ 308 jest dokładną liczbą całkowitą, ale jestem pewien, że tej konkretnej liczby całkowitej nie można dokładnie zapisać w podwójnej liczbie.
Pascal Cuoq,
2

DECIMAL_DIGz <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_RADIXi DBL_MANT_DIG, ale nie jestem pewien, czy całkowicie ufam wynikowi.

Jerry Coffin
źródło
To nie daje odpowiedzi na pytanie. Aby skrytykować lub poprosić autora o wyjaśnienia, zostaw komentarz pod postem.
MichaelChirico
@MichaelChirico: Odpowiada na pytanie, które zamierzał zadać, ponieważ istniało, gdy odpowiedź była napisana. Aby zobaczyć historię edycji pytania, kliknij link „edytowany 19 czerwca 14 o 11:40” u dołu pytania.
Jerry Coffin
twoja odpowiedź brzmi jak komentarz, ponieważ wydaje się, że brakuje pewności / autorytatywności, jaką powinna mieć odpowiedź („powinna dać przynajmniej rozsądne ...” ”dokładnie to, ile… trudno powiedzieć” „Przypuszczam… „). Nie mam specjalistycznej wiedzy na zadane pytanie lub odpowiedź, więc mogę się mylić; po prostu włożyłem moje dwa centy, biorąc pod uwagę, że wysłano mnie tutaj z kolejki recenzji (co, jak sądzę, oznacza, że ​​inni użytkownicy oflagowali twoją odpowiedź).
MichaelChirico
1
@MichaelChirico: Być może mają - nie jesteś jedynym, który nie zna tematu; to, co czyni cię niezwykłym, to fakt, że zdajesz sobie sprawę z tego, że jesteś tego nieświadomy. Większość odpowiedzi, które wydają się wiarygodne na temat dokładności liczby zmiennoprzecinkowej w C, jest po prostu błędna. Na przykład wiele (większość) z powyższych opiera się na fałszywym założeniu, że parametr doubleodpowiada 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.
Jerry Coffin
Rozumiem. Być może sugerowałbym dodanie tych informacji do odpowiedzi.
MichaelChirico