floating-point c# - Unterschied zwischen Dezimal, Float und Double in.NET?




decimal vs (15)

Was ist der Unterschied zwischen decimal , float und double in .NET?

Wann würde jemand eines davon benutzen?


Answers

Ganze Zahlen sind, wie erwähnt, ganze Zahlen. Sie können den Punkt nicht speichern, z. B. .7, .42 und .007. 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 setzen diese Typen von Variablen auf genau die gleiche Weise: Anstatt das Wort int , geben Sie double oder float . So was:

float myFloat;
double myDouble;

( float ist die Abkürzung für "floating point" und bedeutet einfach 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 können Sie bis zu 7 Ziffern in Ihrer Nummer haben. Für double s können Sie bis zu 16 Ziffern haben. Um genau 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 ist eine 64-Bit-Nummer.

Doppelklicken Sie auf Ihre neue Schaltfläche, um den Code zu erhalten. 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 Ihren Doppelknopf. Das Nachrichtenfeld zeigt die Nummer korrekt an. Fügen Sie am Ende jedoch eine weitere Nummer hinzu, und C # wird erneut aufgerundet. Die Moral ist, wenn Sie Genauigkeit wollen, seien Sie vorsichtig beim Runden!


Die Variablentypen Dezimal, Double und Float unterscheiden sich in der Art, in der sie die Werte speichern. Präzision ist der Hauptunterschied, bei dem Float ein Gleitkomma-Datentyp mit einfacher Genauigkeit (32 Bit), Double ein Gleitkomma-Datentyp mit doppelter Genauigkeit (64 Bit) und Dezimalzahl ein 128-Bit Gleitkomma-Datentyp ist.

Float - 32 Bit (7 Ziffern)

Double - 64 Bit (15-16 Ziffern)

Dezimal - 128 Bit (28-29 signifikante Stellen)

Mehr über ... den Unterschied zwischen Dezimal, Float und Double


Das war ein interessanter Thread für mich, denn heute haben wir gerade einen kleinen Fehler gehabt, bei dem decimal weniger genau sind als ein float .

In unserem C # -Code lesen wir numerische Werte aus einer Excel-Tabelle, konvertieren sie in eine decimal und senden diese decimal dann an einen Service, 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);
}

Nun, für fast alle unsere Excel-Werte funktionierte das wunderbar. Aber für einige, sehr kleine Excel-Werte, mit decimal.TryParse verlor den Wert vollständig. Ein solches Beispiel ist

  • cellValue = 0.00006317592

  • Decimal.TryParse (cellValue.ToString (), out-Wert); // würde 0 zurückgeben

Bizarrerweise bestand die Lösung darin, die Excel-Werte zuerst in eine double und dann in eine decimal Zahl zu konvertieren:

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 weniger genau ist als eine decimal , würde dies tatsächlich sicherstellen, dass kleine Zahlen immer noch erkannt werden. Aus irgendeinem Grund konnte double.TryParse tatsächlich so kleine Zahlen decimal.TryParse , während decimal.TryParse sie auf Null decimal.TryParse würde.

Ungerade. Sehr komisch.


Die Variablentypen Dezimal, Double und Float unterscheiden sich in der Art, in der sie die Werte speichern. Präzision ist der Hauptunterschied, bei dem Float ein Gleitkomma-Datentyp mit einfacher Genauigkeit (32 Bit), Double ein Gleitkomma-Datentyp mit doppelter Genauigkeit (64 Bit) und Dezimalzahl ein 128-Bit Gleitkomma-Datentyp ist.

Float - 32 Bit (7 Ziffern)

Double - 64 Bit (15-16 Ziffern)

Dezimal - 128 Bit (28-29 signifikante Stellen)

Der Hauptunterschied besteht darin, dass Floats und Doubles binäre Gleitkommatypen sind und ein Dezimalwert den Wert als Gleitkommaart speichert. Dezimale haben daher eine viel höhere Präzision und werden normalerweise in monetären (finanziellen) oder wissenschaftlichen Berechnungsanwendungen verwendet, die ein hohes Maß an Genauigkeit erfordern. In der Leistung sind Dezimalzahlen jedoch langsamer als Double- und Float-Typen.

Dezimal kann 100% genau jede Zahl innerhalb der Genauigkeit des Dezimalformats darstellen, während Float und Double, nicht alle Zahlen genau wiedergeben können, gerade Zahlen, die innerhalb ihrer jeweiligen Formatpräzision sind.

Dezimal

Im Fall von Finanzanwendungen oder wissenschaftlichen Berechnungen ist es besser, Dezimaltypen zu verwenden, da es Ihnen ein hohes Maß an Genauigkeit bietet und Rundungsfehler leicht zu vermeiden ist

Doppelt

Doppeltypen sind wahrscheinlich der am häufigsten verwendete Datentyp für reale Werte, außer Geld zu handhaben.

Schweben

Es wird hauptsächlich in Grafikbibliotheken verwendet, da sehr hohe Anforderungen an die Verarbeitungsleistung gestellt werden, sowie Situationen, in denen Rundungsfehler auftreten können.


Ich werde nicht viele gute (und einige schlechte) Informationen wiederholen, die bereits in anderen Antworten und Kommentaren beantwortet wurden, aber ich beantworte Ihre Follow-up-Frage mit einem Tipp:

Wann würde jemand eines davon benutzen?

Verwenden Sie den Dezimalwert für die gezählten Werte

Verwenden Sie float / double für Messwerte

Einige Beispiele:

  • Geld (zählen wir Geld oder messen Geld?)

  • Abstand (Zählen wir Abstand oder messen Abstand? *)

  • Scores (zählen wir Scores oder messen 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 nominale Distanz nennen würde, wollen wir vielleicht die Entfernung "zählen". Zum Beispiel haben wir es mit Landzeichen zu tun, die Entfernungen zu Städten zeigen, und wir wissen, dass diese Entfernungen nie mehr als eine Dezimalziffer (xxx.x km) haben.


Das Problem bei all diesen Typen ist, dass eine gewisse Ungenauigkeit besteht UND dass dieses Problem mit kleinen Dezimalzahlen auftreten kann, wie im folgenden Beispiel

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 ist das Problem, dass fMean-fDelta = 1.09999999999, das niedriger ist als 1.1.

Vorsicht: Ich denke, dass das gleiche Problem für andere Zahlen sicherlich existieren kann, weil Dezimal nur ein Doppeltes mit höherer Präzision ist und die Genauigkeit immer ein Limit hat.

Tatsächlich entsprechen Double, Float und Decimal BINARY-Dezimalstellen in COBOL!

Es ist bedauerlich, dass andere in COBOL implementierte numerische Typen in .Net nicht existieren. 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) 


Niemand hat das erwähnt

In den Standardeinstellungen verwenden Floats (System.Single) und Doubles (System.Double) niemals eine Überlaufprüfung, während Decimal (System.Decimal) immer die Überlaufprüfung verwendet.

ich meine

decimal myNumber = decimal.MaxValue;
myNumber += 1;

löst OverflowException aus .

Aber diese nicht:

float myNumber = float.MaxValue;
myNumber += 1;

&

double myNumber = double.MaxValue;
myNumber += 1;

In einfachen Worten:

  1. Die Variablentypen Dezimal, Double und Float unterscheiden sich in der Art, in der sie die Werte speichern.
  2. Präzision ist der Hauptunterschied (Beachten Sie, dass dies nicht der einzige Unterschied ist), wobei float ein Gleitkomma-Datentyp mit einfacher Genauigkeit (32 Bit), Double ein Gleitkomma-Datentyp mit doppelter Genauigkeit (64 Bit) und Dezimalzahl ein 128-Bit ist Gleitkommadatentyp.
  3. Die Übersichtstabelle:

/==========================================================================================
    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 .


Die Dezimalstruktur ist strikt auf finanzmathematische Berechnungen ausgerichtet, die eine Rundungsgenauigkeit relativ intolerant sind. Für wissenschaftliche Anwendungen sind Dezimale jedoch aus mehreren Gründen nicht geeignet:

  • Ein gewisser Genauigkeitsverlust ist in vielen wissenschaftlichen Berechnungen aufgrund der praktischen Grenzen des zu messenden physikalischen Problems oder Artefakts akzeptabel. Genauigkeitsverlust ist im Finanzbereich nicht akzeptabel.
  • Dezimal ist für die meisten Operationen viel (viel) langsamer als float und double, hauptsächlich weil Fließkommaoperationen binär ausgeführt werden, während Dezimalkram in der Basis 10 erledigt wird (dh Floats und Doubles werden von der FPU-Hardware wie MMX / SSE gehandhabt) , während Dezimalstellen in Software berechnet werden).
  • Dezimal hat einen unannehmbar kleineren Wertebereich als doppelt, trotz der Tatsache, dass es mehr Stellen der Genauigkeit unterstützt. Daher kann Decimal nicht verwendet werden, um viele wissenschaftliche Werte zu repräsentieren.

Für Anwendungen wie Spiele und eingebettete Systeme, bei denen Speicher und Leistung beide kritisch sind, ist Float normalerweise der numerische Typ der Wahl, da es schneller und halb so groß wie ein Double ist. Ganzzahlen waren früher die Waffe der Wahl, aber die Fließkomma-Leistung hat in modernen Prozessoren die Ganzzahl überholt. Dezimal ist richtig!


Der Hauptunterschied zwischen diesen beiden ist die Präzision.

float ist eine 32-bit Zahl, double ist eine 64-bit Zahl und decimal ist eine 128-bit Zahl.


  1. Double und Float können bei der Kompilierung und Laufzeit durch eine Ganzzahl Null ohne Ausnahme geteilt werden.
  2. Dezimal kann nicht durch Ganzzahl Null geteilt werden. Die Erstellung wird immer fehlschlagen, wenn Sie das tun.

float ~ ± 1,5 × 10-45 bis ± 3,4 × 1038 -------- 7 Ziffern
doppelt ~ ± 5,0 x 10-324 bis ± 1,7 x 10308 ------ 15 oder 16 Ziffern
dezimal ~ ± 1,0 x 10-28 bis ± 7,9 x 1028 -------- 28 oder 29 Ziffern


Die Perspektive eines Hardware-Designers

Ich glaube, ich sollte dazu die Perspektive eines Hardware-Designers hinzufügen, da ich Gleitkomma-Hardware entwerfe und baue. Wenn Sie wissen, wo der Fehler liegt, kann dies hilfreich sein, um zu verstehen, was in der Software passiert. Letztendlich hoffe ich, dass dies die Gründe dafür erklärt, warum Gleitkommafehler auftreten und sich im Laufe der Zeit anhäufen.

1. Übersicht

Aus technischer Sicht haben die meisten Gleitkommaoperationen einige Fehler, da die Hardware, die die Gleitkommaberechnungen durchführt, an letzter Stelle nur einen Fehler von weniger als einer Hälfte einer Einheit haben muss. Daher wird eine Menge Hardware bei einer Genauigkeit enden, die nur erforderlich ist, um einen Fehler von weniger als der Hälfte einer Einheit an letzter Stelle für eine einzelne Operation zu erzielen, was insbesondere bei der Fließkommadivision problematisch ist. Was eine einzelne Operation ausmacht, hängt davon ab, wie viele Operanden die Einheit benötigt. Für die meisten sind es zwei, aber einige Einheiten benötigen 3 oder mehr Operanden. Aus diesem Grund kann nicht garantiert werden, dass wiederholte Operationen zu einem wünschenswerten Fehler führen, da sich die Fehler mit der Zeit summieren.

2. Standards

Die meisten Prozessoren folgen dem IEEE-754 Standard, aber einige verwenden denormalisierte oder andere Standards. Beispielsweise gibt es in IEEE-754 einen denormalisierten Modus, der die Darstellung sehr kleiner Fließkommazahlen auf Kosten der Genauigkeit ermöglicht. Im Folgenden wird jedoch der normalisierte Modus von IEEE-754 behandelt, der den typischen Betriebsmodus darstellt.

Im IEEE-754-Standard dürfen Hardware-Entwickler jeden Wert für error / epsilon angeben, sofern dieser weniger als eine Hälfte einer Einheit an letzter Stelle ist und das Ergebnis nur weniger als eine Hälfte einer Einheit sein muss Platz für eine Operation. Dies erklärt, warum sich die Fehler bei wiederholten Operationen addieren. Bei IEEE-754-Doppelgenauigkeit ist dies das 54. Bit, da 53 Bits verwendet werden, um den numerischen Teil (normalisiert), auch Mantisse genannt, der Fließkommazahl darzustellen (z. B. die 5.3 in 5.3e5). In den nächsten Abschnitten werden die Ursachen von Hardwarefehlern bei verschiedenen Gleitkommaoperationen genauer beschrieben.

3. Ursache für Rundungsfehler in der Division

Die Hauptursache für den Fehler in der Gleitkommadivision sind die zur Berechnung des Quotienten verwendeten Divisionsalgorithmen. Die meisten Computersysteme berechnen die Division unter Verwendung der Multiplikation mit einer Inversen, hauptsächlich in Z=X/Y , Z = X * (1/Y) . Eine Division wird iterativ berechnet, dh jeder Zyklus berechnet einige Bits des Quotienten, bis die gewünschte Genauigkeit erreicht ist, was für IEEE-754 irgendetwas mit einem Fehler von weniger als einer Einheit an letzter Stelle ist. Die Tabelle der Kehrwerte von Y (1 / Y) ist in der langsamen Division als Quotientenauswahltabelle (QST) bekannt, und die Größe der Bits der Quotientenauswahltabelle ist normalerweise die Breite der Basis oder eine Anzahl von Bits der in jeder Iteration berechnete Quotient plus ein paar Schutzbits. Für den IEEE-754-Standard mit doppelter Genauigkeit (64 Bit) wäre dies die Größe der Basis des Teilers plus ein paar Schutzbits k, wobei k>=2 . Eine typische Quotienten-Auswahltabelle für einen Teiler, der jeweils 2 Bits des Quotienten (Radix 4) berechnet, wäre beispielsweise 2+2= 4 Bits (plus einige optionale Bits).

3.1 Rundungsfehler der Division: Annäherung an das Reziproke

Was in der Quotienten-Auswahltabelle wechselseitig ist, hängt von der Divisionsmethode ab : langsame Division wie SRT-Division oder schnelle Division wie Goldschmidt-Division; Jeder Eintrag wird gemäß dem Divisionsalgorithmus modifiziert, um den geringstmöglichen Fehler zu erzielen. In jedem Fall sind jedoch alle Kehrwerte Annäherungen an den tatsächlichen Kehrwert und führen zu Fehlern. Sowohl das langsame als auch das schnelle Divisionsverfahren berechnen den Quotienten iterativ, dh in jedem Schritt werden einige Bits des Quotienten berechnet, dann wird das Ergebnis vom Dividenden abgezogen, und der Dividierer wiederholt die Schritte, bis der Fehler weniger als eine Hälfte beträgt Einheit an letzter Stelle. Langsame Teilungsmethoden berechnen eine feste Anzahl von Stellen des Quotienten in jedem Schritt und sind in der Regel kostengünstiger in der Erstellung, und schnelle Teilungsmethoden berechnen eine variable Anzahl von Ziffern pro Schritt und sind in der Regel teurer in der Erstellung. Der wichtigste Teil der Divisionsmethoden besteht darin, dass die meisten von ihnen auf wiederholte Multiplikation durch Annäherung eines Reziproken angewiesen sind, so dass sie fehleranfällig sind.

4. Rundungsfehler bei anderen Vorgängen: Abschneiden

Eine weitere Ursache für Rundungsfehler bei allen Operationen sind die unterschiedlichen Abschneidemodi der endgültigen Antwort, die IEEE-754 zulässt. Es wird abgeschnitten, auf Null abgerundet, auf den nächstgelegenen Wert (Standard), aufgerundet und gerundet. Alle Methoden führen für eine einzelne Operation an letzter Stelle ein Fehlerelement von weniger als einer Einheit ein. Im Laufe der Zeit und bei wiederholten Operationen fügt die Kürzung auch den resultierenden Fehler kumulativ hinzu. Dieser Verkürzungsfehler ist besonders problematisch bei der Exponentiation, die eine Form wiederholter Multiplikation beinhaltet.

5. Wiederholte Operationen

Da die Hardware, die die Gleitkommaberechnungen durchführt, nur ein Ergebnis mit einem Fehler von weniger als der Hälfte einer Einheit an letzter Stelle für eine einzelne Operation liefern muss, wird der Fehler bei wiederholten Operationen größer, wenn sie nicht überwacht wird. Dies ist der Grund dafür, dass Mathematiker bei Berechnungen, die einen begrenzten Fehler erfordern, Methoden wie das Verwenden der runden zu nächsten geraden Ziffer an letzter Stelle von IEEE-754 verwenden, da sich die Fehler im Laufe der Zeit mit größerer Wahrscheinlichkeit gegenseitig aufheben out und Intervallarithmetik kombiniert mit Variationen der Rundungsmodi nach IEEE 754 , um Rundungsfehler vorherzusagen und zu korrigieren. Aufgrund seines geringen relativen Fehlers im Vergleich zu anderen Rundungsmodi, auf die nächste gerade Zahl gerundet (an letzter Stelle), ist dies der Standardrundungsmodus von IEEE-754.

Beachten Sie, dass der voreingestellte Rundungsmodus, der letzten Stelle , die gerade auf die letzte gerade Zahl ist , einen Fehler von weniger als der Hälfte einer Einheit an letzter Stelle für eine Operation garantiert. Die alleinige Verwendung von Abschneiden, Aufrunden und Abrunden kann zu einem Fehler führen, der an letzter Stelle größer als die Hälfte einer Einheit ist, an letzter Stelle jedoch weniger als eine Einheit. Daher werden diese Modi nur empfohlen, wenn dies der Fall ist Wird in Intervallarithmetik verwendet.

6. Zusammenfassung

Kurz gesagt, der grundlegende Grund für die Fehler bei Fließkommaoperationen ist eine Kombination aus der Verkürzung der Hardware und der Verkürzung eines Kehrwerts bei Divisionen. Da der IEEE-754-Standard für eine einzelne Operation an letzter Stelle nur einen Fehler von weniger als der Hälfte einer Einheit erfordert, summieren sich die Gleitkommafehler bei wiederholten Operationen, sofern sie nicht korrigiert werden.





.net floating-point double decimal