2012-06-07 2 views
12

Wenn hat ein Doppel eine ‚genaue‘ Integer-Wert, etwa so:Wenn ein Double mit einem ganzzahligen Wert in eine ganze Zahl umgewandelt wird, ist es dann garantiert "richtig"?

double x = 1.0; 
double y = 123123; 
double z = -4.000000; 

ist sichergestellt, dass es richtig zu 1, 123123 abrunden wird, und -4, wenn sie über (int) auf einen ganzzahligen Typ umgewandelt x , (int) y, (int) z? (Und nicht auf 0, 123122 oder -5 b/c von Fließkomma-Seltsamkeit abgeschnitten). Ich frage b/c nach this page (das ist über fp in Lua, eine Sprache, die standardmäßig nur seinen numerischen Typ verdoppelt), spricht darüber, wie Integer-Operationen mit doubles sind genau nach IEEE 754, aber ich bin mir nicht sicher wenn ich beim Aufruf von C-Funktionen mit Integer-Typ-Parametern die doppelte Verdopplung manuell vornehmen muss, oder wenn man darauf achtet, dass die Double-Werte ganzzahlige Werte haben.

+0

Sie sollten hier einige Punkte klären a) durch double do du meinst 8 Bytes oder 4 Bytes und b) mit richtig meinst du rund geht gegen Null? – JaredPar

+0

Mögliches Duplikat: http://stackoverflow.com/questions/9154687/validity-of-checking-exact-value-of-preset-double – Ruben

+1

Es findet kein "Runden" statt. Die Besetzung führt Abschneiden durch. –

Antwort

9

Ja, Wenn passt der Ganzzahlwert in int.

Ein double könnte ganzzahlige Werte darstellen, die außerhalb des Bereichs für Ihren Typ int liegen. Beispiel: 123123.0 kann nicht in int konvertiert werden, wenn der Typ int nur 16 Bit hat.

Es ist auch nicht garantiert, dass ein double jeden Wert darstellen kann, den ein bestimmter Typ darstellen kann. IEEE 754 verwendet so etwas wie 52 oder 53 Bits für die Mantisse. Wenn Ihr long 64 Bits hat, dann kann die Umwandlung eines sehr großen long in double und zurück nicht den gleichen Wert ergeben.

+0

Der Standard gibt diese Garantie für Werte, deren integraler Teil in dem Zieltyp in 6.3.1.4 dargestellt werden kann: "Wenn ein endgültiger Wert von Real floating type wird in einen anderen Integer-Typ als _Bool konvertiert, der Nachkommaanteil wird verworfen (dh der Wert wird in Richtung Null abgeschnitten). Wenn der Wert des Integralteils nicht durch den Integer-Typ dargestellt werden kann, ist das Verhalten nicht definiert. " –

+0

@DanielFischer: Danke für die Referenz. Ich habe die Antwort aktualisiert. –

0

Ja, es wird den genauen Wert halten, den Sie ihm geben, weil Sie es in Code eingeben. Manchmal in Berechnungen würde es ,99999999999 zum Beispiel ergeben, aber das ist aufgrund des Fehlers bei der Berechnung mit Doppel nicht seine Speicherkapazität

1

Es wird es richtig tun, wenn es wirklich ist wahr ganz Zahl, die Sie sicher sein, könnten in einige Kontexte. Wenn der Wert jedoch das Ergebnis früherer Fließkommaberechnungen ist, können Sie dies nicht leicht erkennen.

Warum nicht explizit den Wert mit der Funktion floor() berechnen, wie in long value = floor(x + 0.5). Oder, noch besser, verwenden Sie die modf() Funktion, um nach einem ganzzahligen Wert zu suchen.

+0

Wenn Sie wissen, dass der Wert eine ganze Zahl ist, gibt es keinen Vorteil bei der Verwendung der Funktion floor() vs.ein Cast (außer wenn die Sprache keinen Integer-Typ hat, zB Lua, JS) – finnw

3

Wie Daniel Fischer sagte, wenn der Wert des ganzzahligen Teils des Double (in Ihrem Fall das Double genau) in dem Typ, in den Sie konvertieren, darstellbar ist, ist das Ergebnis exakt. Wenn der Wert außerhalb des Bereichs des Zieltyps liegt, ist das Verhalten nicht definiert. "Undefiniert" bedeutet, dass der Standard jedes Verhalten zulässt: Sie könnten die nächste darstellbare Zahl erhalten, Sie könnten Null bekommen, Sie könnten eine Ausnahme bekommen, oder der Computer könnte explodieren. (Hinweis: Während der C-Standard Ihrem Computer erlaubt, zu explodieren oder sogar das Universum zu zerstören, ist es wahrscheinlich, dass die Spezifikationen des Herstellers eine strengere Grenze für das Verhalten festlegen.)

+2

Trotz meiner Leichtfertigkeit über undefiniertes Verhalten möchte ich darauf hinweisen, dass es ernsthafte Konsequenzen hat. Angenommen, Sie gehen davon aus, dass einige Ergebnisse falsch sind, weil sie außerhalb des zulässigen Bereichs liegen. Sie werden jedoch nach der Konvertierung erkannt und verworfen. Eine unbeabsichtigte Konsequenz des Optimierers des Compilers ist, dass er, wenn er beweisen kann, dass Ihr Code undefiniertes Verhalten bekommt, Ihren Code und alles, was ihn aufruft, durch absichtliche Programm-Exits oder irgendeinen anderen Code ersetzen kann. –

Verwandte Themen