Was ist die größte "nicht schwebende" Ganzzahl, die in einem IEEE 754-Doppeltyp gespeichert werden kann, ohne an Genauigkeit zu verlieren?
Was ist die größte "nicht schwebende" Ganzzahl, die in einem IEEE 754-Doppeltyp gespeichert werden kann, ohne an Genauigkeit zu verlieren?
Antworten:
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_MAX
oder 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 :
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.
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
double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);
der das gleiche Ergebnis liefert
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.
while (dbl + 1 != dbl) dbl++;
, dass dbl + 1 != dbl
bewerten kann mit long double
Mathematik - prüfen FLT_EVAL_METHOD == 2
. Dies könnte in einer Endlosschleife enden.
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.
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:
0x7FE
(2046, der 1023 darstellt, nachdem die Vorspannung subtrahiert wurde) anstelle von 0x7FF
(2047, der a NaN
oder unendlich anzeigt ).0xFFFFFFFFFFFFF
die 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 .
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.
1,7976931348623157 × 10 ^ 308
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
DECIMAL_DIG
from <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_RADIX
und herausfinden können DBL_MANT_DIG
, aber ich bin mir nicht sicher, ob ich dem Ergebnis vollständig vertrauen würde.
double
direkt 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.