Frage

Ich habe diese einfache Codezeile:

float val = 123456.123456;

Wenn ich diesen Val drucke oder in den Umfang schaue, speichert er den Wert 123456.13

Ok, es ist in Ordnung, es kann nicht all diese Ziffern nach Punkt in 4 Bytes speichern, aber warum macht es 13 nach dem Punkt? Sollte es nicht 12 sein?

(Mit VC ++ 2010 Express auf Win32)

War es hilfreich?

Lösung

Wenn Sie als Schwimmer dargestellt werden, hat Ihre Zahl einen Exponenten von 16 (dh der Wert ist die Mantisse -Zeiten 2^16 oder 65536). Der Mantisse wird dann

123456.123456 / 65536 = 1.8837909462890625

Um in einen 32-Bit-Schwimmer zu passen 1.883791. Wenn sich mit einer Multiplizierung mit dem Multiplizieren 65536, es wird 123456.125.

Beachten Sie das 5 In der dritten Position nach dem Dezimalpunkt: Die Ausgangsroutine von C ++, die Sie verwendet haben 123456.13.

BEARBEITEN Erklärung der Rundung: (Rick Regans Kommentar)

Die Rundung erfolgt zuerst in Binär (bis 24 Bit), in dezimaler bis binärer Umwandlung und dann in Dezimaler in printf. Der gespeicherte Wert beträgt 1.1110001001000000001 x 2^16 = 1,8837909698486328125 x 2^16 = 123456.125. Es druckt als 123456.13, jedoch nur, weil Visual C ++ "runde halbe Ablauf von Zero" verwendet.

Rick hat eine Hervorragender Artikel zu diesem Thema, zu.

Wenn Sie mit anderen Zahlen und ihren Float -Darstellungen spielen möchten, hier ist a Sehr nützlicher IEEE-754-Taschenrechner.

Andere Tipps

In Binary ist 123456.123456 111100010010000.000.00011111001 ... (unendlich). Es rundet 11110001001000000.001 oder 123456.125. Dass Runden bis 123456.13 beim Druck.

Der Wert in gespeicherter Wert val ist gleich 123456.125. Sie bekommen .13 Weil du es rundst:

float val = 123456.123456;
printf("%.4f %.2f\n", val, val);

Ausgang: 123456.1250 123456.13

Sie sollten in diesem Fall doppelt verwenden, um Kürzung zu vermeiden. Compiler sollte Sie auch warnen: "Warnung C4305: 'Initialisierung': Kürzung von 'Double' zu 'Float'".

Versuchen Sie, den Wert von zu drucken std::numeric_limits<float>::digits10. Dies ist grob gesagt, wie viel Präzision in Basis 10 ein Float hat. Sie versuchen, es zu übertreffen, sodass Sie einen Präzisionsverlust erleben (was bedeutet, dass Ziffern, die über die bedeutenden hinausgehen, nicht wirklich sinnvoll sind).

Siehe zB Was bedeutet numeric_limitsu003Cdouble> :: Digits10

Es ist völlig Compiler abhängig. Überprüfen Sie es in GCC. Es sollte xxx.12 sein

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top