Was ist der Unterschied zwischen dem Umwandeln in „float“ und dem Hinzufügen von „f“ als Suffix beim Initialisieren eines „float“?

Lesezeit: 5 Minuten

Was ist der Unterschied zwischen

float f = (float) 99.32 ;

und

float f = 99.32f ;

Beide wurden erfolgreich kompiliert und ausgeführt.

  • Der erste leidet darunter doppelter Rundungsfehler, was nicht gut ist, da das Ergebnis möglicherweise nicht den gewünschten Wert hat. Der zweite erzeugt einen korrekt gerundeten Float-Wert en.wikipedia.org/wiki/Rounding#Double_rounding

    – phuklv

    16. Oktober 2015 um 8:15 Uhr


  • Dieser Link verwendet eine viel zu lange Darstellung seiner Beispielnummer. “0.50000008940696713” ist ausreichend.

    – Random832

    16. Oktober 2015 um 16:13 Uhr

  • @LưuVĩnhPhúc: Ich gehe davon aus, dass eine genaue Dezimaldarstellung eines Werts auf halbem Weg zwischen zwei benachbarten Doppelwerten verwendet wurde, obwohl ich vorschlagen würde, dass das Hinzufügen einer großen Ganzzahl zum Wert präzise Dezimaldarstellungen viel kürzer und offensichtlicher machen würde.

    – Superkatze

    16. Oktober 2015 um 19:09 Uhr


  • 1. Meinen Sie speziell für diese Dezimalzeichenfolge oder für eine beliebige? 2. Was bedeutet „erfolgreich“? “Den gleichen Wert zurückgegeben”? (Testen sie als gleich? Haben Sie das untersucht gesamte Darstellung?)

    – Philippie

    21. Oktober 2015 um 8:38 Uhr

Benutzeravatar von Magisch
Magisch

float f = 99.32f ;

Das ist ein float Literal, was bedeutet, dass eine Float-Variable mit a zugewiesen wird float Wert direkt.

float f = (float) 99.32 ;

Das ist ein float Variable, der a zugewiesen wird double Wert, auf den gecastet wird float vor der Zuweisung.

  • Würde der Compiler dies optimieren? (im Gussfall)

    – Austi01101110

    16. Oktober 2015 um 7:12 Uhr

  • nein, 99.32 ist ein Fließkommaliteral, das den Typ hat double.

    – mch

    16. Oktober 2015 um 8:14 Uhr


  • nein, 99.32 ist ein double, nicht implizit darauf gecastet. Dies wird als “Gleitkommaliteraltyp” bezeichnet double“. 99.32f ist ein float und nicht dazu gecastet. Dies wird als “Gleitkommaliteraltyp” bezeichnet float“. Es gibt keine Besetzung bei float f = 99.32f; oder double d = 99.32;.

    – mch

    16. Oktober 2015 um 8:23 Uhr

  • Gibt es einen Wertunterschied zwischen den beiden?

    – John Dvorak

    16. Oktober 2015 um 13:53 Uhr

  • @JanDvorak: Selten und in diesem Fall wahrscheinlich nicht. (Float) 99,32 ist die reelle Zahl 99,32, gerundet auf die nächste verfügbare Double-Zahl, gerundet auf die nächste verfügbare Float-Zahl. 99,32f ist die reelle Zahl 99,32, gerundet auf die nächste Gleitkommazahl. Sei x eine Zahl, die genau in der Mitte zwischen zwei benachbarten Gleitkommazahlen liegt. Seien d und d’ zwei Dezimalzahlen, die nur ein winziges bisschen größer/kleiner als x sind. Dann würde das .f-Suffix auf-/abgerundet werden, aber das Runden auf das Doppelte könnte in beiden Fällen das Ergebnis x ergeben, und das Casting auf float würde entweder d oder d’ in die falsche Richtung runden.

    – gnasher729

    16. Oktober 2015 um 22:41 Uhr


Benutzeravatar von skyking
Himmel König

Der Unterschied kann wegoptimiert werden, aber im ersten Fall haben Sie ein doppeltes Literal, das in einen Float umgewandelt wird, während Sie im zweiten Fall ein Float-Literal haben.

Wenn Sie nicht wegoptimiert sind, erhalten Sie im zweiten Beispiel eine Typumwandlung im Code.

Es gibt jedoch Ausnahmefälle, in denen das Ergebnis (je nach Rundungsmodus) geringfügig abweichen kann. Wenn Ihre Zahl nicht genau dargestellt werden kann, wird im ersten Fall zweimal gerundet – zuerst, wenn Sie die Dezimaldarstellung auf ein Double runden, und dann, wenn Sie diese auf einen Float runden, während Sie im ersten Fall die Dezimaldarstellung direkt runden zu einem Schwimmer.

  • Da ein ULP mit einfacher Genauigkeit so viel größer ist als ein ULP mit doppelter Genauigkeit, kann ich kaum glauben, dass die doppelte Rundung einen signifikanten Effekt haben könnte.

    – Kevin

    16. Oktober 2015 um 13:31 Uhr

  • @Kevin Es hätte eine Wirkung von bis zu eins schweben ULP-Unterschied.

    – John Dvorak

    16. Oktober 2015 um 13:54 Uhr

  • Ich vermute, dass es einen Eckfall gibt, habe ihn aber nicht gefunden.

    – chux – Wiedereinsetzung von Monica

    16. Oktober 2015 um 15:18 Uhr

  • 0,50000008940696713 ergibt ein anderes Ergebnis: mit Rundung erhält man 0x1.000004p-1 während Sie mit Suffix erhalten 0x1.000002p-1 (sehen ideone.com/EV3QeG). Siehe auch en.wikipedia.org/wiki/Rounding#Double_rounding

    – Matthias M.

    16. Oktober 2015 um 17:59 Uhr


  • Genauer gesagt, die letzten beiden Ziffern von 11-21 ergeben alle 0x1.000003p-1 als doppelt (und daher 0x1.000004p-1 wenn doppelt gerundet auf Float) und die letzten beiden Ziffern von 11-16 (ungefähr die Hälfte dieses Bereichs) ergeben 0x1.000002p-1. Der Wertebereich, über den dies auftreten kann (für jeden Fall vermutlich mit einem Abstand von einem ULP-Float), ist ungefähr die Hälfte eines doppelten ULP breit und ergibt in jedem Fall einen “Fehler” von einem halben ULP-Float, wenn gerundet wird nach oben oder unten, da die realen Werte ungefähr in der Mitte zwischen zwei Float-Werten liegen.

    – Random832

    16. Oktober 2015 um 18:36 Uhr


Im ersten Fall ohne Besetzung 99.32 wird als Double und nicht als Float interpretiert.

Ein doppeltes Literal wird gecastet, um zu schweben.

Im zweiten Fall haben Sie ein Suffix f um sicherzustellen, dass der Compiler behandelt 99.32 als Schwimmer.

Benutzeravatar von code_dredd
code_dredd

In der Schlange float f = (float) 99.32; das wörtliche 99.32 wird erstellt als double Typ standardmäßig und wird dann in a umgewandelt float.

In der Schlange float f = 99.32f ; das Literal wird als a erstellt float Typ aufgrund des Nachgestellten f in 99.32f und es ist kein Typcasting erforderlich.

Letzteres wäre analog zum Schreiben double f = 99.32; wie du hättest double Typ direkt einer Variablen eines übereinstimmenden Typs zugewiesen wird.

Benutzeravatar von 101010
101010

Fließkommaliterale ohne Suffix sind standardmäßig double Typ.

So heißt es float f = (float) 99.32; du wirfst zuerst ausdrücklich wörtlich 99.32 was vom Typ ist double zu einem float und dann der Variablen zuweisen f.

Angeben float f = 99.32; macht das gleiche, aber in diesem Fall die Die Konvertierung zwischen den Typen erfolgt implizit.

Wenn Sie eine implizite Konvertierung vermeiden möchten, sollten Sie die verwenden f Suffix, um Ihr Literal zu definieren (d. h. float f = 99.32f;)

  • nein, sie sind nicht dasselbe, ohne die f Suffix ist das Ergebnis manchmal falsch

    – phuklv

    17. April um 10:32 Uhr

Evdzhan Mustafas Benutzeravatar
Evdzhan Mustafa

Der Unterschied besteht darin, dass das wörtliche 99.32 ist vom Typ double, während das Literal 99.32f ist vom Typ Float.

Die erste Anweisung weist das Float-Literal einer Float-Variablen zu. Nichts Besonderes.

Die zweite Anweisung wandelt ein Double-Literal in einen Float um und weist das Ergebnis einer Float-Variablen zu.

Standardmäßig können Sie einer Float-Variablen ein Double-Literal zuweisen, ohne es explizit selbst zu casten. In diesem Fall erfolgt eine implizite Umwandlung. Z.B :

float f = 99.32;

Sie können sogar Folgendes tun:

float f = (double) 10.5f;

und die rechte Seite wird immer noch implizit in einen Float umgewandelt.

Bitte beachten Sie, dass die meisten modernen Compiler diese wegoptimieren, sodass die Darstellung von Gleitkommazahlen normalerweise eine Frage des Stils und der Präferenz ist. Sei einfach konsequent.

  • nein, sie sind nicht dasselbe, ohne die f Suffix ist das Ergebnis manchmal falsch

    – phuklv

    17. April um 10:32 Uhr

1414670cookie-checkWas ist der Unterschied zwischen dem Umwandeln in „float“ und dem Hinzufügen von „f“ als Suffix beim Initialisieren eines „float“?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy