größte Ganzzahl, die doppelt gespeichert werden kann

225

Was ist die größte "nicht schwebende" Ganzzahl, die in einem IEEE 754-Doppeltyp gespeichert werden kann, ohne an Genauigkeit zu verlieren?

Franck Freiburger
quelle

Antworten:

505

Die größte / größte Ganzzahl, die in einem Double gespeichert werden kann, ohne an Genauigkeit zu verlieren, entspricht dem größtmöglichen Wert eines Double. Das heißt, DBL_MAXoder ungefähr 1,8 × 10 308 (wenn Ihr Double ein IEEE 754 64-Bit-Double ist). Es ist eine ganze Zahl. Es ist genau dargestellt. Was willst du noch?

Fragen Sie mich weiter, was die größte Ganzzahl ist, damit sie und alle kleineren Ganzzahlen in IEEE 64-Bit-Doubles gespeichert werden können, ohne an Genauigkeit zu verlieren. Ein IEEE 64-Bit-Double hat 52 Mantisse-Bits, also denke ich, dass es 2 53 ist :

  • 2 53 + 1 kann nicht gespeichert werden, da die 1 am Anfang und die 1 am Ende zu viele Nullen dazwischen haben.
  • Alles, was kleiner als 2 53 ist, kann gespeichert werden, wobei 52 Bits explizit in der Mantisse gespeichert sind und der Exponent Ihnen tatsächlich einen weiteren gibt.
  • 2 53 kann natürlich gespeichert werden, da es sich um eine kleine Potenz von 2 handelt.

Oder eine andere Sichtweise: Sobald die Vorspannung vom Exponenten entfernt wurde und das Vorzeichenbit als für die Frage irrelevant ignoriert wurde, ist der von einem Double gespeicherte Wert eine Potenz von 2 plus eine 52-Bit-Ganzzahl multipliziert mit 2 Exponent - 52 . Mit Exponent 52 können Sie also alle Werte von 2 52 bis 2 53  - 1 speichern. Mit Exponent 53 ist die nächste Zahl, die Sie nach 2 53 speichern können, 2 53 + 1 × 2 53 - 52 . Ein Präzisionsverlust tritt also zuerst bei 2 53 + 1 auf.

Steve Jessop
quelle
126
+1 Gute Arbeit, als ich bemerkte, dass die Frage nicht wirklich bedeutete, was der Fragesteller wahrscheinlich beabsichtigte, und beide Antworten lieferte ("technisch korrekt" und "wahrscheinlich erwartet").
Pascal Cuoq
62
Oder "herumspielen" und "versuchen zu helfen", wie ich sie nenne :-)
Steve Jessop
8
Ich verneige mich vor Tony dem Pony und keinem anderen.
Steve Jessop
11
Sie meinen nicht "alle kleineren ganzen Zahlen", sondern alle ganzen Zahlen gleicher oder geringerer Größe. Weil es viele negative ganze Zahlen unter 2 ^ 53 gibt und nicht genau in einem Doppel dargestellt werden kann.
Southern Hospitality
13
Ich meine kleiner, und genau das meine ich, wenn ich kleiner sage :-) -1.000.000 ist kleiner als 1, aber nicht kleiner.
Steve Jessop
77

9007199254740992 (das sind 9.007.199.254.740.992) ohne Garantie :)

Programm

#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;
}

Ergebnis

9007199254740991
9007199254740992
9007199254740992
pmg
quelle
7
Angenommen, es ist "nah", aber weniger als 2 ^ N, dann ist ein schnellerer Test, double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);der das gleiche Ergebnis liefert
Seph
4
@Seph was zum ...? Nein? while (dbl == --dbl)wird für immer oder gar nicht schleifen. :) (in diesem Fall überhaupt nicht, da es sich um eine 2 ^ N handelt). Sie müssen es von unten nähern. Es wird in der Tat auch zu einem Ergebnis führen, das unter dem erwarteten Ergebnis liegt (da das Einchecken in der while-Schleife dbl dekrementiert). Und es hängt von der Reihenfolge der Ausführung ab, ob die Dekrementierung vor oder nach der Auswertung der linken Seite erfolgt (was meines Wissens undefiniert ist). Wenn es das erstere ist, wird es immer wahr sein und für immer eine Schleife bilden.
Falstro
10
Vielleicht geben Sie an, dass 2 ^ 53 = 9.007.199.254.740.992 irgendwo ist.
Xonatron
1
Es ist schwer damit zu streiten! Schönes Experiment
MattM
Eine Schwäche zu verwenden while (dbl + 1 != dbl) dbl++;, dass dbl + 1 != dblbewerten kann mit long doubleMathematik - prüfen FLT_EVAL_METHOD == 2. Dies könnte in einer Endlosschleife enden.
chux
25

Wikipedia hat dies im gleichen Zusammenhang mit einem Link zu IEEE 754 zu sagen :

Auf einem typischen Computersystem hat eine binäre Gleitkommazahl mit doppelter Genauigkeit (64 Bit) einen Koeffizienten von 53 Bit (von denen eines impliziert ist), einen Exponenten von 11 Bit und ein Vorzeichenbit.

2 ^ 53 ist etwas mehr als 9 * 10 ^ 15.

Carl Smotricz
quelle
@ Steve Jessop mehr oder weniger, das ist in der Tat, was ich sage. Ich bin auch auf Hardwaresysteme gestoßen, die keine FPU haben, die noch IEEE-kompatibel sein muss, so dass "typisches System" mir nicht wirklich hilft, wenn ich 8 Monate später hierher zurückkomme und die gleichen Informationen für benötige mein 68K-basierter Mikrocontroller (vorausgesetzt, er hat keine FPU ... ich kann mich nicht erinnern).
San Jacinto
14
@ San Jacinto - "Das ist nutzlos" ist übermäßig hart. Die Antwort ist sehr nützlich, nur nicht so nützlich, wie es gewesen wäre, wenn sie den Kommentar enthalten hätte, dass typische Computersysteme tatsächlich die IEEE 754-Repräsentation verwenden.
Stephen C. Steel
@ Stephen C. Steel, eigentlich bist du richtig. Unter meinem Szenario, wenn ich zu einem späteren Zeitpunkt darauf zurückkomme und nach dem IEEE-Maximum suche, ist es unmöglich zweideutig, was ein "typisches System" ist, aber die Antwort ist neben dieser Beschwerde immer noch sinnvoll.
San Jacinto
20

Die größte Ganzzahl, die in IEEE 754 double (64-Bit) dargestellt werden kann, entspricht dem größten Wert, den der Typ darstellen kann, da dieser Wert selbst eine Ganzzahl ist.

Dies wird dargestellt als 0x7FEFFFFFFFFFFFFF, das sich zusammensetzt aus:

  • Das Vorzeichenbit 0 (positiv) statt 1 (negativ)
  • Der maximale Exponent 0x7FE(2046, der 1023 darstellt, nachdem die Vorspannung subtrahiert wurde) anstelle von 0x7FF(2047, der a NaNoder unendlich anzeigt ).
  • Die maximale Mantisse, 0xFFFFFFFFFFFFFdie 52 Bit alle 1 ist.

Im Binärbereich ist der Wert die implizite 1, gefolgt von weiteren 52 Einsen von der Mantisse und 971 Nullen (1023 - 52 = 971) vom Exponenten.

Der genaue Dezimalwert ist:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368

Dies ist ungefähr 1,8 x 10 308 .

Simon Biber
quelle
Was ist mit dem größten Wert, den es darstellen kann, wobei alle Werte zwischen ihm und Null zusammenhängend darstellbar sind?
Aaron Franke
@AaronFranke Die Frage fragte nicht nach zusammenhängender Darstellung, aber die Antwort auf diese andere Frage wurde in den meisten anderen Antworten hier aufgenommen oder sogar fälschlicherweise als tatsächliche Antwort angegeben. Es ist 2³ (2 hoch 53).
Simon Biber
8

Sie müssen sich die Größe der Mantisse ansehen. Eine IEEE 754 64-Bit-Gleitkommazahl (mit 52 Bit plus 1 impliziten) kann genau ganze Zahlen mit einem Absolutwert von weniger als oder gleich 2 ^ 53 darstellen.

Delfin
quelle
8
Es kann auch genau 2 ^ 53 darstellen :-)
Steve Jessop
6

1,7976931348623157 × 10 ^ 308

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

Jay
quelle
2
Diese Antwort wäre mit einem Zitat viel besser.
San Jacinto
2
@Carl Nun, wenn die Ganzzahl links darüber hinaus Nullen hat, wird sie genau gespeichert.
Wilhelm
4
@all you downvoters: 1.7976931348623157 × 10 ^ 308 ist eine exakte Ganzzahl. Müssen Sie alle an Mathematikkursen teilnehmen oder so?
Dan Moulding
6
Bei der Diskussion dieser hoffnungslos versunkenen Antwort geht es hier um die Semantik. Diese Zahl kann zwar genau dargestellt werden und erfüllt damit den Buchstaben der Frage. Aber wir alle wissen, dass es sich um eine winzige Insel der Genauigkeit in einem Ozean von Beinaheunfällen handelt, und die meisten von uns haben die Frage richtig interpoliert, um "die größte Zahl zu bedeuten, ab der Präzision den Bach runtergeht". Ah, ist es nicht wunderbar, dass CompSci eine exakte Wissenschaft ist? :)
Carl Smotricz
2
@DanMoulding 1.7976931348623157 × 10 ^ 308 ist eine exakte Ganzzahl, aber ich bin mir ziemlich sicher, dass diese bestimmte Ganzzahl nicht genau doppelt gespeichert werden kann.
Pascal Cuoq
2

DECIMAL_DIGfrom <float.h>sollte zumindest eine vernünftige Annäherung daran geben. Da die sich mit Dezimalstellen, und es ist wirklich binär gespeichert ist, können Sie wahrscheinlich speichern etwas ein wenig größer , ohne Präzision zu verlieren, aber genau , wie viel ist schwer zu sagen. Ich nehme an, Sie sollten es aus FLT_RADIXund herausfinden können DBL_MANT_DIG, aber ich bin mir nicht sicher, ob ich dem Ergebnis vollständig vertrauen würde.

Jerry Sarg
quelle
Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klarstellung zu bitten, hinterlassen Sie einen Kommentar unter seinem Beitrag.
MichaelChirico
@MichaelChirico: Dies beantwortet die Frage, die er stellen wollte, wie sie existierte, als die Antwort geschrieben wurde. Um den Bearbeitungsverlauf der Frage anzuzeigen, klicken Sie unten in der Frage auf den Link "bearbeitet am 19. Juni 14 um 11:40 Uhr".
Jerry Coffin
Ihre Antwort liest sich wie ein Kommentar, weil es anscheinend an Vertrauen / Autorität mangelt, die eine Antwort haben sollte ("sollte zumindest ein vernünftiges ..." "genau wie viel ... ist schwer zu sagen" "Ich nehme an ... "). Ich habe kein Fachwissen über die gestellte Frage oder die Antwort, daher kann ich mich irren. Ich habe nur meine zwei Cent eingegeben, da ich aus der Überprüfungswarteschlange hierher geschickt wurde (was bedeutet, dass andere Benutzer Ihre Antwort markiert haben).
MichaelChirico
1
@ MichaelChirico: Sie haben vielleicht - Sie sind weit davon entfernt, der einzige zu sein, der das Thema nicht kennt; Was dich ungewöhnlich macht, ist, dass du erkennst, dass du nichts davon weißt. Die meisten Antworten, die für die Genauigkeit einer Gleitkommazahl in C maßgeblich sind, sind einfach falsch. Zum Beispiel basieren viele (die meisten) von ihnen auf der falschen Annahme, dass a doubledirekt einem bestimmten IEEE-Typ entspricht, aber das ist nicht erforderlich, und als diese Antwort geschrieben wurde, erwähnte die Frage auch keinen bestimmten IEEE-Typ.
Jerry Coffin
Ich habs. Ich würde vielleicht vorschlagen, diese Informationen zur Antwort hinzuzufügen.
MichaelChirico