2015-08-26 12 views

Antwort

1

Vs2008 verwendete Gleitkomma-Literale mit 80 Bit und rundete diesen präziseren Wert bei der Konvertierung in ein Double ab.

Vs2015 tut dies nicht und schneidet nur das Literal ab.

Ich glaube, Sie können zwischen den beiden Schemas durch Ändern der Compilereinstellungen wechseln.

+0

Das Visual C++ 2008-Ergebnis ist tatsächlich weniger korrekt. Siehe meine Antwort für Details. –

+0

Sie sind der Experte! Ich werde dies löschen und Ihre Antwort aufwerten. – Bathsheba

+0

Bevor ich es aber tun konnte, konnten Sie bestätigen, dass vs2008 80-Bit-Literale standardmäßig nicht verwendet hat? (Dh die Standardeinstellungen des Compilers). Ich erinnere mich, dass ich vor ein paar Jahren so etwas gesehen habe. – Bathsheba

9

Wir haben den Fließkomma-Parser und Formatierer für the Universal CRT und Visual C++ 2015 umgeschrieben, um die Korrektheit zu verbessern. Siehe die Breaking Changes in Visual C++ Dokumentation für Visual C++ 2015; Es gibt einen Abschnitt mit dem Titel "Gleitkommaformatierung und Parsing".

Das Visual C++ 2015-Ergebnis ist das korrekt gerundete Ergebnis. Das Eingabestring 0.182696884245135 ist mit dem folgenden Wert mit doppelter Genauigkeit umgewandelt, die der nächste darstellbare Wert ist:

0.18269688424513'49994693288181224488653242588043212890625 

Beachten Sie die Häkchen nach dem 14. Nachkommastelle. Die 15. Ziffer ist eine 4, wenn also die Zahl mit 14 Nachkommastellen formatiert wird, wird die Zahl "abgerundet" (oder abgeschnitten), nicht nach oben.

Das Visual C++ 2008-Ergebnis ist falsch. Ich weiß nicht, ob beim Parsen oder Formatieren ein Fehler aufgetreten ist. Es gibt keine Möglichkeit, das alte, falsche Verhalten mit dem Universal CRT und Visual C++ 2015 zu erhalten.

+0

Vielen Dank für Ihre Antwort James. Diese Änderung verursachte jedoch ein Problem für unsere Kunden. sprintf_s (buf, "%. * f", 2, 0.155) verursacht nun zB 0,15 anstelle von 0,16. Gibt es eine Möglichkeit, das alte sprintf_s Verhalten durch andere Rundungsfunktionen nachzuahmen? –

+0

Das ist auch das richtige Ergebnis: Der nächstgelegene darstellbare Wert ist '0.154999 ... ', der auf' 0.15 'abgerundet wird, nicht auf' 0.16 '. Die alte Implementierung wurde in beiden Richtungen (nach oben und nach unten) falsch gerundet. Es gibt keine andere Möglichkeit, genau das falsche Verhalten zu erhalten, das mit der alten Implementierung (mit Visual C++ 2013 oder früher) nicht zu erreichen ist. Sie können sicherlich versuchen, numerische Vergleiche zu machen, um zu sehen, "ist dieses Ding ziemlich nah an der Hälfte?"(für eine Definition von" ziemlich nah ") und passen Sie die Nummer selbst an, wie Sie für richtig halten. –