Beispiel:
float timeRemaining = 0.58f;
Warum ist das f
am Ende dieser Nummer erforderlich?
c#
floating-point
Thomas
quelle
quelle
double
.double & int
.Antworten:
Ihre Erklärung eines Schwimmers besteht aus zwei Teilen:
timeRemaining
vom Typ istfloat
.0.58
dieser Variablen den Wert zu.Das Problem tritt in Teil 2 auf.
Die rechte Seite wird einzeln ausgewertet. Gemäß der C # -Spezifikation wird eine Zahl mit einem Dezimalpunkt ohne Suffix als a interpretiert
double
.Wir haben jetzt einen
double
Wert, den wir einer Variablen vom Typ zuweisen möchtenfloat
. Dazu muss eine implizite Konvertierung vondouble
nach erfolgenfloat
. Es gibt keine solche Konvertierung, da Sie möglicherweise (und in diesem Fall) Informationen in der Konvertierung verlieren.Der Grund dafür ist, dass der vom Compiler verwendete Wert nicht wirklich 0,58 ist, sondern der Gleitkommawert, der 0,58 am nächsten kommt, also 0,57999999999999978655962351581366 ... für
double
und genau 0,579999946057796478271484375 fürfloat
.Genau genommen ist das
f
nicht erforderlich. Sie können die Verwendung desf
Suffix vermeiden, indem Sie den Wert in a umwandelnfloat
:quelle
(float) 0.58
Arbeit funktionieren? Sie haben vorhin gesagt, dass es keine Konvertierung gibt, da möglicherweise Informationen verloren gehen. Wie kommt es dann, dass die Besetzung funktioniert?2.4
wird überall anders als Doppel interpretiert. 2. Implizite Verengungskonvertierungen (wie von Double zu Float) sind nicht zulässig. Wenn Sie eine Ausnahme von diesen Regeln machen möchten, müssen Sie einen sehr guten Grund haben. Das Speichern von 1 Tastendruck ist wahrscheinlich nicht gut genug.Da es mehrere numerische Typen gibt, mit denen der Compiler den Wert darstellen kann
0.58
:float
,double
unddecimal
. Sofern Sie nicht damit einverstanden sind, dass der Compiler einen für Sie auswählt, müssen Sie eindeutig unterscheiden.In der Dokumentation für
double
heißt es, dass der Compiler immerdouble
den Typ eines reellen numerischen Literals auswählt, wenn Sie den Typ nicht selbst angeben :Durch Anhängen des Suffixes
f
wird einfloat
; das Suffixd
erzeugt eindouble
; Das Suffixm
erstellt eindecimal
. All dies funktioniert auch in Großbuchstaben.Dies reicht jedoch immer noch nicht aus, um zu erklären, warum dies nicht kompiliert wird:
Die fehlende Hälfte der Antwort besteht darin, dass bei der Konvertierung von
double
0.58
zufloat
timeRemaining
möglicherweise Informationen verloren gehen, sodass der Compiler sich weigert, diese implizit anzuwenden. Wenn Sie eine explizite Umwandlung hinzufügen, wird die Konvertierung durchgeführt. Wenn Sie dasf
Suffix hinzufügen, ist keine Konvertierung erforderlich. In beiden Fällen würde der Code dann kompiliert.quelle
int
und eine fürdouble
.double a = 0.69f;
?float
in einschließtdouble
.Das Problem ist , dass .NET, um einige Arten von impliziten Operationen zu ermöglichen , durchgeführt werden , die mit
float
unddouble
mußten entweder explizit angeben , was in allen Szenarien mit gemischten Operanden oder auch erlaubt implizite Konvertierungen zwischen den Typen in einer durchgeführt werden , geschehen soll , nur Richtung; Microsoft entschied sich dafür, dem Beispiel von Java zu folgen, indem es die Richtung zuließ, die gelegentlich die Präzision fördert, aber häufig die Korrektheit opfert und im Allgemeinen Ärger verursacht.In fast allen Fällen, die unter
double
Wert, der am nächsten an eine bestimmte numerische Größe ist und es eine Zuordnungfloat
wird die Ausbeutefloat
Wert, der am nächsten zu der gleichen Größe ist. Es gibt einige Eckfälle, z. B. den Wert 9.007.199.791.611.905; Die bestefloat
Darstellung wäre 9.007.200.328.482.816 (was 536.870.911 entspricht), aber die bestedouble
Darstellung (dh 9.007.199.791.611.904)float
ergibt 9.007.199.254.740.992 (was 536.870.913 entspricht). Im Allgemeinen ergibt die Konvertierung der bestendouble
Darstellung einer bestimmten Menge infloat
entweder die bestmöglichefloat
Darstellung oder eine von zwei Darstellungen, die im Wesentlichen gleich gut sind.Beachten Sie, dass dieses wünschenswerte Verhalten auch im Extremfall gilt. Beispielsweise
float
stimmt die beste Darstellung für die Menge 10 ^ 308 mit derfloat
Darstellung überein, die durch Konvertieren der bestendouble
Darstellung dieser Menge erreicht wird. Ebensofloat
stimmt die beste Darstellung von 10 ^ 309 mit derfloat
Darstellung überein, die durch Konvertieren der bestendouble
Darstellung dieser Größe erreicht wird.Leider sind Konvertierungen in die Richtung, für die keine explizite Besetzung erforderlich ist, selten annähernd so genau. Das Konvertieren der besten
float
Darstellung eines Wertes in ergibtdouble
selten etwas, das der bestendouble
Darstellung dieses Wertes besonders nahe kommt , und in einigen Fällen kann das Ergebnis um Hunderte von Größenordnungen abweichen (z. B. das Konvertieren der bestenfloat
Darstellung von 10 ^ 40 indouble
ergibt einen Wert Ein Wert, der größer ist als die bestedouble
Darstellung von 10 ^ 300.Leider sind die Konvertierungsregeln so, wie sie sind. Daher muss man beim Konvertieren von Werten in die "sichere" Richtung mit albernen Typecasts und Suffixen leben und auf implizite Typecasts in der gefährlichen Richtung achten, die häufig zu falschen Ergebnissen führen.
quelle