Was ist der Unterschied zwischen decimal
, float
und double
in .NET?
Wann würde jemand eines davon verwenden?
.net
floating-point
double
decimal
PC Luddite
quelle
quelle
Antworten:
float
unddouble
sind schwimmend binäre Punkttypen . Mit anderen Worten, sie repräsentieren eine Zahl wie diese:Die Binärzahl und die Position des Binärpunkts werden beide innerhalb des Werts codiert.
decimal
ist ein schwimmender dezimaler Punkt - Typ . Mit anderen Worten, sie repräsentieren eine Zahl wie diese:Auch hier werden sowohl die Zahl als auch die Position des Dezimalpunkts innerhalb des Werts codiert - das macht
decimal
immer noch einen Gleitkommatyp anstelle eines Festpunkttyps aus.Es ist wichtig zu beachten, dass Menschen es gewohnt sind, Nicht-Ganzzahlen in Dezimalform darzustellen und genaue Ergebnisse in Dezimaldarstellungen zu erwarten. Nicht alle Dezimalzahlen können im binären Gleitkomma genau dargestellt werden (z. B. 0,1). Wenn Sie also einen binären Gleitkommawert verwenden, erhalten Sie tatsächlich eine Annäherung an 0,1. Sie erhalten auch weiterhin Annäherungen, wenn Sie einen Gleitkommapunkt verwenden - das Ergebnis der Division von 1 durch 3 kann beispielsweise nicht genau dargestellt werden.
Was ist zu verwenden, wenn:
Für Werte, die "natürlich exakte Dezimalstellen" sind, ist es gut zu verwenden
decimal
. Dies ist normalerweise für alle vom Menschen erfundenen Konzepte geeignet: Finanzielle Werte sind das offensichtlichste Beispiel, aber es gibt auch andere. Betrachten Sie zum Beispiel die Punktzahl für Taucher oder Eisläufer.Für Werte , die mehr Artefakte der Natur sind , die nicht wirklich gemessen werden kann , genau wie auch immer,
float
/double
sind besser geeignet. Beispielsweise würden wissenschaftliche Daten normalerweise in dieser Form dargestellt. Hier sind die ursprünglichen Werte zunächst nicht "dezimal genau", daher ist es für die erwarteten Ergebnisse nicht wichtig, die "dezimale Genauigkeit" beizubehalten. Gleitende Binärpunkttypen sind viel schneller zu verarbeiten als Dezimalstellen.quelle
float
/double
In der Regel stellt keine Zahlen , wie101.101110
, in der Regel wird es als so etwas wie dargestellt1101010 * 2^(01010010)
- Exponentfloat
ein C # -Alias-Schlüsselwort ist und kein .Net-Typ. es istSystem.Single
..single
unddouble
sind Gleitkomma-Binärpunkttypen.Präzision ist der Hauptunterschied.
Float - 7 Stellen (32 Bit)
Doppelte -15-16 Stellen (64 Bit)
Dezimal -28-29 signifikante Stellen (128 Bit)
Dezimalstellen haben eine viel höhere Präzision und werden normalerweise in Finanzanwendungen verwendet, die ein hohes Maß an Genauigkeit erfordern. Dezimalstellen sind viel langsamer (in einigen Tests bis zu 20-mal) als ein Double / Float.
Dezimalstellen und Floats / Doubles können nicht ohne Besetzung verglichen werden, während Floats und Doubles dies können. Dezimalstellen ermöglichen auch die Codierung oder nachgestellten Nullen.
Ergebnis:
quelle
0.1
- das ist in der realen Welt selten der Fall! Jedes endliche Speicherformat kombiniert eine unendliche Anzahl möglicher Werte mit einer endlichen Anzahl von Bitmustern. Zum Beispielfloat
wird zusammenfließen0.1
und0.1 + 1e-8
, währenddecimal
wird zusammenfließen0.1
und0.1 + 1e-29
. Sicher, innerhalb eines bestimmten Bereichs können bestimmte Werte in jedem Format ohne Genauigkeitsverlust dargestellt werden (z. B.float
können beliebige Ganzzahlen bis zu 1,6e7 ohne Genauigkeitsverlust gespeichert werden) - aber das ist immer noch keine unendliche Genauigkeit.0.1
ist kein besonderer Wert ! Das einzige , was macht0.1
„besser“ als0.10000001
ist , weil Menschen wie Basis 10 und sogar mit einemfloat
Wert, wenn man zwei Werte mit initialisieren0.1
die gleiche Art und Weise, werden sie beide den gleichen Wert sein . Es ist nur so, dass dieser Wert nicht genau ist0.1
- es ist der Wert, der dem am nächsten kommt0.1
, der genau als dargestellt werden kannfloat
. Sicher, mit binären Gleitkommazahlen,(1.0 / 10) * 10 != 1.0
aber auch mit dezimalen Gleitkommazahlen(1.0 / 3) * 3 != 1.0
. Weder ist vollkommen präzise.double a = 0.1; double b = 0.1;
danna == b
wird wahr sein . Es ist nur so , dassa
undb
wird beide nicht genau gleich0.1
. In C #, wenn Sie das tun ,decimal a = 1.0m / 3.0m; decimal b = 1.0m / 3.0m;
danna == b
wird auch der Fall sein. Aber in diesem Fall weder vona
nochb
wird genau gleich1/3
- sie werden beide gleich0.3333...
. In beiden Fällen geht aufgrund der Darstellung eine gewisse Genauigkeit verloren. Sie sagen hartnäckig, dass diesdecimal
"unendliche" Präzision hat, was falsch ist .Die Dezimalstruktur ist streng auf finanzielle Berechnungen ausgerichtet, die Genauigkeit erfordern und die Rundungen relativ unverträglich sind. Dezimalstellen sind für wissenschaftliche Anwendungen jedoch aus mehreren Gründen nicht ausreichend:
quelle
Weitere Informationen finden Sie hier .
quelle
Ich werde nicht viele gute (und einige schlechte) Informationen wiederholen, die bereits in anderen Antworten und Kommentaren beantwortet wurden, aber ich werde Ihre Folgefrage mit einem Tipp beantworten:
Verwenden Sie für gezählte Werte eine Dezimalzahl
Verwendung float / double für Messwerte
Einige Beispiele:
Geld (zählen wir Geld oder messen wir Geld?)
Entfernung (zählen wir die Entfernung oder messen wir die Entfernung? *)
Scores (zählen wir Scores oder messen wir Scores?)
Wir zählen immer Geld und sollten es niemals messen. Wir messen normalerweise die Entfernung. Wir zählen oft Punkte.
* In einigen Fällen, was ich als nominelle Entfernung bezeichnen würde , möchten wir möglicherweise tatsächlich die Entfernung "zählen". Vielleicht haben wir es mit Länderzeichen zu tun, die Entfernungen zu Städten anzeigen, und wir wissen, dass diese Entfernungen niemals mehr als eine Dezimalstelle (xxx.x km) haben.
quelle
float
7 Stellen Genauigkeitdouble
hat ungefähr 15 Stellen Genauigkeitdecimal
hat ungefähr 28 Stellen GenauigkeitWenn Sie eine bessere Genauigkeit benötigen, verwenden Sie double anstelle von float. In modernen CPUs haben beide Datentypen fast die gleiche Leistung. Der einzige Vorteil der Verwendung von Float ist, dass sie weniger Platz beanspruchen. Praktisch nur wichtig, wenn Sie viele davon haben.
Ich fand das interessant. Was jeder Informatiker über Gleitkomma-Arithmetik wissen sollte
quelle
double
in Buchhaltungsanwendungen in den Fällen (und im Grunde nur in den Fällen), in denen kein Integer-Typ größer als 32 Bit verfügbar war und derdouble
als 53-Bit-Integer-Typ verwendet wurde (z. B. zum Halten), als richtig erachten eine ganze Anzahl von Pennys oder eine ganze Anzahl von Hundertstel Cent). Heutzutage wird für solche Dinge nicht viel verwendet, aber viele Sprachen haben die Fähigkeit erlangt, Gleitkommawerte mit doppelter Genauigkeit zu verwenden, lange bevor sie 64-Bit- (oder in einigen Fällen sogar 32-Bit-!) Ganzzahlmathematik erlangt haben.Real
IIRC jedoch Werte bis zu 1,8E + 19 mit Einheitsgenauigkeit darstellen konnte. Ich würde denken, es wäre viel vernünftiger für eine Buchhaltungsanwendung,Real
eine ganze Anzahl von Pennysdouble
Typ mit einer Einheitsgenauigkeit von bis zu 9E15. Wenn man ganze Zahlen speichern muss, die größer als der größte verfügbare Integer-Typ sind, ist die Verwendungdouble
einfacher und effizienter als der Versuch, die Mathematik mit mehrfacher Genauigkeit zu verfälschen, insbesondere angesichts der Tatsache, dass Prozessoren Anweisungen zur Ausführung von 16x16-> 32 oder haben. ..Niemand hat das erwähnt
ich meine
löst eine OverflowException aus .
Aber diese nicht:
&
quelle
float.MaxValue+1 == float.MaxValue
genauso wiedecimal.MaxValue+0.1D == decimal.MaxValue
. Vielleicht hast du so etwas gemeintfloat.MaxValue*2
?System.Decimal
löst eine Ausnahme aus, kurz bevor es nicht mehr möglich ist, ganze Einheiten zu unterscheiden. Wenn eine Anwendung jedoch z. B. Dollar und Cent verarbeiten soll, kann dies zu spät sein.quelle
decimal
durch Null zu teilen (CS0020). Dies gilt auch für integrale Literale. Wenn jedoch ein Laufzeit-Dezimalwert durch Null geteilt wird, erhalten Sie eine Ausnahme, keinen Kompilierungsfehler.Ganzzahlen sind, wie erwähnt, ganze Zahlen. Sie können den Punkt nicht wie .7, .42 und .007 speichern. Wenn Sie Zahlen speichern müssen, die keine ganzen Zahlen sind, benötigen Sie einen anderen Variablentyp. Sie können den Double-Typ oder den Float-Typ verwenden. Sie richten diese Variablentypen genauso ein: Anstatt das Wort zu verwenden
int
, geben Siedouble
oder einfloat
. So was:(
float
steht für "Gleitkomma" und bedeutet nur eine Zahl mit einem Punkt am Ende.)Der Unterschied zwischen den beiden liegt in der Größe der Zahlen, die sie halten können. Für
float
Sie können bis zu 7 Ziffern in Ihrer Nummer haben. Fürdouble
s können Sie bis zu 16 Ziffern haben. Um genauer zu sein, hier ist die offizielle Größe:float
ist eine 32-Bit-Nummer unddouble
eine 64-Bit-Nummer.Doppelklicken Sie auf Ihre neue Schaltfläche, um zum Code zu gelangen. Fügen Sie Ihrem Schaltflächencode die folgenden drei Zeilen hinzu:
Halten Sie Ihr Programm an und kehren Sie zum Codierungsfenster zurück. Ändern Sie diese Zeile:
Führen Sie Ihr Programm aus und klicken Sie auf die Doppelschaltfläche. Das Meldungsfeld zeigt die Nummer korrekt an. Fügen Sie am Ende jedoch eine weitere Zahl hinzu, und C # wird erneut aufgerundet. Die Moral ist, wenn Sie Genauigkeit wollen, achten Sie auf Rundungen!
quelle
quelle
decimal
wird tatsächlich im Dezimalformat gespeichert (im Gegensatz zu Basis 2; so werden durch die Konvertierung zwischen den beiden numerischen Systemen keine Ziffern verloren oder gerundet);decimal
Darüber hinaus gibt es kein Konzept für spezielle Werte wie NaN, -0, ∞ oder -∞.Dies war ein interessanter Thread für mich, da wir heute gerade einen bösen kleinen Fehler hatten,
decimal
weil wir weniger Präzision als a hattenfloat
.In unserem C # -Code lesen wir numerische Werte aus einer Excel-Tabelle, konvertieren sie in eine
decimal
und senden siedecimal
dann an einen Dienst zurück, um sie in einer SQL Server- Datenbank zu speichern.Für fast alle unsere Excel-Werte hat dies wunderbar funktioniert. Bei einigen sehr kleinen Excel-Werten
decimal.TryParse
ging der Wert jedoch vollständig verloren. Ein solches Beispiel istcellValue = 0,00006317592
Decimal.TryParse (cellValue.ToString (), out value); // würde 0 zurückgeben
Seltsamerweise bestand die Lösung darin, die Excel-Werte zuerst in eine
double
und dann in eine zu konvertierendecimal
:Obwohl
double
es weniger präzise als a istdecimal
, stellte dies tatsächlich sicher, dass kleine Zahlen immer noch erkannt werden. Aus irgendeinem Grunddouble.TryParse
war es tatsächlich möglich, so kleine Zahlen abzurufen, währenddecimal.TryParse
sie auf Null gesetzt würden.Seltsam. Sehr komisch.
quelle
decimal.Parse("0.00006317592")
funktioniert - da ist noch etwas los. - Möglicherweise wissenschaftliche Notation?Für Anwendungen wie Spiele und eingebettete Systeme, bei denen sowohl Speicher als auch Leistung von entscheidender Bedeutung sind, ist Float normalerweise der numerische Typ der Wahl, da es schneller und halb so groß wie ein Double ist. Früher waren Ganzzahlen die Waffe der Wahl, aber die Gleitkomma-Leistung hat die Ganzzahl in modernen Prozessoren überholt. Dezimal ist richtig!
quelle
Die Variablentypen Decimal, Double und Float unterscheiden sich in der Art und Weise, wie sie die Werte speichern. Die Genauigkeit ist der Hauptunterschied, bei dem Gleitkomma ein Gleitkomma-Datentyp mit einfacher Genauigkeit (32 Bit) ist, double ein Gleitkomma-Datentyp mit doppelter Genauigkeit (64 Bit) und decimal ein 128-Bit-Gleitkomma-Datentyp.
Float - 32 Bit (7 Stellen)
Double - 64 Bit (15-16 Stellen)
Dezimal - 128 Bit (28-29 signifikante Stellen)
Mehr über ... den Unterschied zwischen Decimal, Float und Double
quelle
Das Problem bei all diesen Typen ist, dass eine bestimmte Ungenauigkeit besteht UND dass dieses Problem bei kleinen Dezimalzahlen wie im folgenden Beispiel auftreten kann
Frage: Welchen Wert enthält die Variable bLower?
Antwort: Auf einer 32-Bit-Maschine enthält bLower TRUE !!!
Wenn ich Double durch Decimal ersetze, enthält bLower FALSE, was die gute Antwort ist.
Im doppelten Fall besteht das Problem darin, dass fMean-fDelta = 1.09999999999 ist, was niedriger als 1.1 ist.
Achtung: Ich denke, dass das gleiche Problem sicherlich für andere Zahlen bestehen kann, da Dezimal nur ein Doppel mit höherer Genauigkeit ist und die Genauigkeit immer eine Grenze hat.
Tatsächlich entsprechen Double, Float und Decimal der BINARY-Dezimalstelle in COBOL!
Es ist bedauerlich, dass andere in COBOL implementierte numerische Typen in .Net nicht vorhanden sind. Für diejenigen, die COBOL nicht kennen, gibt es in COBOL folgenden numerischen Typ
quelle
In einfachen Worten:
quelle
Decimal
für Finanzanwendungen geeignet und das Hauptkriterium für die Entscheidung zwischenDecimal
undDouble
. Es ist beispielsweise selten, dassDouble
Präzision für wissenschaftliche Anwendungen nicht ausreicht (und für wissenschaftliche Anwendungen aufgrund ihres begrenzten BereichsDecimal
oft ungeeignet ist).Der Hauptunterschied zwischen diesen ist die Präzision.
float
ist eine32-bit
Zahl,double
ist eine64-bit
Zahl unddecimal
ist eine128-bit
Zahl.quelle
Dezimalzahl 128 Bit (28-29 signifikante Stellen) Bei Finanzanwendungen ist es besser, Dezimaltypen zu verwenden, da dies ein hohes Maß an Genauigkeit bietet und Rundungsfehler leicht zu vermeiden sind. Verwenden Sie Dezimalstellen für nicht ganzzahlige Mathematik, wenn Präzision erforderlich ist (z Geld und Währung)
Double 64 Bit (15-16 Stellen) Double Types sind wahrscheinlich der am häufigsten verwendete Datentyp für reale Werte, außer für den Umgang mit Geld. Verwenden Sie double für nicht ganzzahlige Mathematik, bei der die genaueste Antwort nicht erforderlich ist.
Float 32 Bit (7 Stellen) Es wird hauptsächlich in Grafikbibliotheken verwendet, da sehr hohe Anforderungen an die Verarbeitungsleistung gestellt werden und auch Situationen verwendet werden, in denen Rundungsfehler auftreten können.
Decimals
sind viel langsamer als eindouble/float
.Decimals
undFloats/Doubles
kann nicht ohne Besetzung verglichen werden, währendFloats
undDoubles
kann.Decimals
Erlauben Sie auch die Kodierung oder nachgestellten Nullen.quelle
So definieren Sie Dezimal, Float und Double in .Net (c #)
Sie müssen Werte wie folgt angeben:
und überprüfen Sie die Ergebnisse.
Und die von jedem belegten Bytes sind
quelle