Der folgende Code löst eine Ausnahme von std :: out_of_range in Visual Studio 2013 aus, wo es meiner Meinung nach nicht sollte:
%Vor% Ich habe den Code auch mit gcc 4.9.2 getestet und dort gibt es keine Ausnahme. Das Problem scheint durch eine ungenaue Zeichenfolgendarstellung nach der Konvertierung in Zeichenfolge verursacht worden zu sein. In Visual Studio liefert std::to_string(std::numeric_limits<double>::max())
179769313486231610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,000000
das scheint tatsächlich zu groß. In gcc ergibt es jedoch
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368,000000
scheint kleiner zu sein als der übergebene Wert.
Allerdings soll nicht std::numeric_limits<double>::max()
das
maximale endliche darstellbare Fließkommazahl?
Warum steigen die String-Darstellungen aus? Was fehlt mir hier?
Gcc (und Clang und VS2105) geben korrekt den ganzzahligen Wert von (2 1024 - 1) - (2 1024-53 - 1) zurück, was dargestellt ist mit 52 Ein-Bit-Signifikanden und einem unverzerrten Exponenten von 1023 (2 1024 - 1 wäre der ganzzahlige Wert mit 1023 Ein-Bits, und ich subtrahiere nur alle Bits unterhalb der 52 des IEE754-Formats <) / p>
Ich kann bestätigen, dass eine große Integer-Bibliothek 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368L
Der vorherige exakte Fließkommawert wäre 2 971 kleiner (971 = 1023 - 52), also: 179769313486231550856124328384506240234343437157459335924404872448581845754556114388470639943126220321960804027157371570809852884964511743044087662767600909594331927728237078876188760579532563768698654064825262115771015791463983014857704008123419459386245141723703148097529108423358883457665451722744025579520L
Der nächste nicht darstellbare Wert wäre 2 971 größer, also:
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216L
Aber der von MSVC2013 und früher verwendete Wert liegt nahe bei 2 1024 + 2 971 , das heißt: 179769313486231610731333614426100589925524828262616317947942685512308090830973387504827396012048193870699768806228404251083258210739369062217227314575410731769485876273179688476358949112102859294830297395714877595371718127781702814782017661749531126051903195165027873311156314696040132728420308633064323416064L
. Da es größer ist als jeder Wert, der in IEEE754 mit doppelter Genauigkeit dargestellt werden kann, kann es nicht zu einem Doppel dekodiert werden.
Denn höchstens könnte man sagen, dass jeder Wert zwischen 2 1024 - 2 971 ( std::numeric_limits<double>::max()
) und 2 1024 sein könnte gerundet auf std::numeric_limits<double>::max()
, aber Werte größer als 2 1024 sind eindeutig ein Überlauf.
In einem Double sind nur 16 Dezimalziffern korrekt und alle anderen Ziffern können als Müll- oder Zufallswerte betrachtet werden, da sie nicht vom Wert selbst abhängen, sondern nur von der Art, wie Sie sie berechnen. Versuche einfach 1e + 288 (das ist schon ein großer Wert) auf maxDbl
zu subtrahieren und schau was passiert:
Sie sollten sehen ... Unverändert.
Es sieht so aus, als ob VS 2013 ein wenig inkohärent in der Art ist, wie Gleitkommawerte gerundet werden: es hat maxDbl durch Überschreitung auf ein Bit höher als den maximal darstellbaren Wert gerundet und konnte es nicht entschlüsseln später.
Das Problem ist, dass der Standard ein %f
-Format verwendet, was ein falsches Gefühl der Genauigkeit ergibt. Wenn Sie ein äquivalentes Problem in gcc sehen möchten, verwenden Sie einfach:
Abgerundet auf 16 Ziffern mxDbl schreibt (korrekt): 1.797693134862316e + 308, kann aber nicht mehr zurückdecodiert werden
Und dieser:
%Vor%Anzeigen:
%Vor%TL / DR: Was ich meine ist, dass ein großer Enoudh-Double-Wert natürlich durch eine exakte ganze Zahl repräsentiert werden kann (nach IEEE754). Aber es repräsentiert alle ganzen Zahlen zwischen der Hälfte der vorherigen und der Hälfte der nächsten. Daher kann jede Ganzzahl in diesem Bereich eine akzeptable Darstellung für das Double sein, und ein Wert gerundet bei 16 Dezimalziffern sollte akzeptabel sein, aber die aktuellen Standardbibliotheken erlauben nur, dass der maximale Gleitkommawert abgeschnitten wird bei 16 Dezimalziffern. Aber VS2013 gab eine Zahl über dem Maximum des Bereichs, was auf jeden Fall ein Fehler war.
Tags und Links c++ gcc visual-studio type-conversion