Was ist der Unterschied zwischen decimal
, float
und double
in .NET?
Wann würde jemand eines davon verwenden?
Was ist der Unterschied zwischen decimal
, float
und double
in .NET?
Wann würde jemand eines davon verwenden?
Antworten:
float
und double
sind schwimmend binäre Punkttypen . Mit anderen Worten, sie repräsentieren eine Zahl wie diese:
10001.10010110011
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:
12345.65789
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.
float
/ double
In der Regel stellt keine Zahlen , wie 101.101110
, in der Regel wird es als so etwas wie dargestellt 1101010 * 2^(01010010)
- Exponent
float
ein C # -Alias-Schlüsselwort ist und kein .Net-Typ. es ist System.Single
.. single
und double
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.
float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);
Ergebnis:
float: 0.3333333
double: 0.333333333333333
decimal: 0.3333333333333333333333333333
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 Beispiel float
wird zusammenfließen 0.1
und 0.1 + 1e-8
, während decimal
wird zusammenfließen 0.1
und 0.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 macht 0.1
„besser“ als 0.10000001
ist , weil Menschen wie Basis 10 und sogar mit einem float
Wert, wenn man zwei Werte mit initialisieren 0.1
die gleiche Art und Weise, werden sie beide den gleichen Wert sein . Es ist nur so, dass dieser Wert nicht genau ist 0.1
- es ist der Wert, der dem am nächsten kommt 0.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;
dann a == b
wird wahr sein . Es ist nur so , dass a
und b
wird beide nicht genau gleich 0.1
. In C #, wenn Sie das tun , decimal a = 1.0m / 3.0m; decimal b = 1.0m / 3.0m;
dann a == b
wird auch der Fall sein. Aber in diesem Fall weder von a
noch b
wird genau gleich 1/3
- sie werden beide gleich 0.3333...
. In beiden Fällen geht aufgrund der Darstellung eine gewisse Genauigkeit verloren. Sie sagen hartnäckig, dass dies decimal
"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:
+---------+----------------+---------+----------+---------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32768 to 32767 |
| int | System.Int32 | Yes | 4 | -2147483648 to 2147483647 |
| long | System.Int64 | Yes | 8 | -9223372036854775808 to 9223372036854775807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65535 |
| uint | System.UInt32 | No | 4 | 0 to 4294967295 |
| ulong | System.Uint64 | No | 8 | 0 to 18446744073709551615 |
| float | System.Single | Yes | 4 | Approximately ±1.5 x 10-45 to ±3.4 x 1038 |
| | | | | with 7 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
| | | | | with 15 or 16 significant figures |
| decimal | System.Decimal | Yes | 12 | Approximately ±1.0 x 10-28 to ±7.9 x 1028 |
| | | | | with 28 or 29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------+
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:
Wann würde jemand eines davon verwenden?
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.
float
7 Stellen Genauigkeit
double
hat ungefähr 15 Stellen Genauigkeit
decimal
hat ungefähr 28 Stellen Genauigkeit
Wenn 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
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 der double
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 Pennys
double
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 Verwendung double
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
In den Standardeinstellungen verwenden Floats (System.Single) und Doubles (System.Double) niemals die Überlaufprüfung, während Decimal (System.Decimal) immer die Überlaufprüfung verwendet.
ich meine
decimal myNumber = decimal.MaxValue;
myNumber += 1;
löst eine OverflowException aus .
Aber diese nicht:
float myNumber = float.MaxValue;
myNumber += 1;
&
double myNumber = double.MaxValue;
myNumber += 1;
float.MaxValue+1 == float.MaxValue
genauso wie decimal.MaxValue+0.1D == decimal.MaxValue
. Vielleicht hast du so etwas gemeint float.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.
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 Sie double
oder ein float
. So was:
float myFloat;
double myDouble;
( 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ür double
s können Sie bis zu 16 Ziffern haben. Um genauer zu sein, hier ist die offizielle Größe:
float: 1.5 × 10^-45 to 3.4 × 10^38
double: 5.0 × 10^-324 to 1.7 × 10^308
float
ist eine 32-Bit-Nummer und double
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:
double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());
Halten Sie Ihr Programm an und kehren Sie zum Codierungsfenster zurück. Ändern Sie diese Zeile:
myDouble = 0.007;
myDouble = 12345678.1234567;
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!
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 sie decimal
dann an einen Dienst zurück, um sie in einer SQL Server- Datenbank zu speichern.
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
decimal value = 0;
Decimal.TryParse(cellValue.ToString(), out value);
}
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 ist
cellValue = 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 konvertieren decimal
:
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
double valueDouble = 0;
double.TryParse(cellValue.ToString(), out valueDouble);
decimal value = (decimal) valueDouble;
…
}
Obwohl double
es weniger präzise als a ist decimal
, stellte dies tatsächlich sicher, dass kleine Zahlen immer noch erkannt werden. Aus irgendeinem Grund double.TryParse
war es tatsächlich möglich, so kleine Zahlen abzurufen, während decimal.TryParse
sie auf Null gesetzt würden.
Seltsam. Sehr komisch.
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!
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
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
Dim fMean as Double = 1.18
Dim fDelta as Double = 0.08
Dim fLimit as Double = 1.1
If fMean - fDelta < fLimit Then
bLower = True
Else
bLower = False
End If
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
BINARY or COMP like float or double or decimal
PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
ZONED-DECIMAL (1 digit in 1 byte)
In einfachen Worten:
/==========================================================================================
Type Bits Have up to Approximate Range
/==========================================================================================
float 32 7 digits -3.4 × 10 ^ (38) to +3.4 × 10 ^ (38)
double 64 15-16 digits ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308)
decimal 128 28-29 significant digits ±7.9 x 10 ^ (28) or (1 to 10 ^ (28)
/==========================================================================================
Sie können hier mehr lesen , Float , Double und Decimal .
Decimal
für Finanzanwendungen geeignet und das Hauptkriterium für die Entscheidung zwischen Decimal
und Double
. Es ist beispielsweise selten, dass Double
Präzision für wissenschaftliche Anwendungen nicht ausreicht (und für wissenschaftliche Anwendungen aufgrund ihres begrenzten Bereichs Decimal
oft ungeeignet ist).
Der Hauptunterschied zwischen diesen ist die Präzision.
float
ist eine 32-bit
Zahl, double
ist eine 64-bit
Zahl und decimal
ist eine 128-bit
Zahl.
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 ein double/float
.
Decimals
und Floats/Doubles
kann nicht ohne Besetzung verglichen werden, während Floats
und Doubles
kann.
Decimals
Erlauben Sie auch die Kodierung oder nachgestellten Nullen.
Sie müssen Werte wie folgt angeben:
Decimal dec = 12M/6;
Double dbl = 11D/6;
float fl = 15F/6;
und überprüfen Sie die Ergebnisse.
Float - 4
Double - 8
Decimal - 12