Unterschied zwischen Dezimal, Float und Double in .NET?


Antworten:


2267

floatund doublesind 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.

decimalist 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 decimalimmer 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/ doublesind 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.


58
float/ doubleIn der Regel stellt keine Zahlen , wie 101.101110, in der Regel wird es als so etwas wie dargestellt 1101010 * 2^(01010010)- Exponent
Mingwei Samuel

79
@Hazzard: Das bedeutet der Teil "und die Position des Binärpunkts" der Antwort.
Jon Skeet

112
Ich bin überrascht, dass es noch nicht gesagt wurde, floatein C # -Alias-Schlüsselwort ist und kein .Net-Typ. es ist System.Single.. singleund doublesind Gleitkomma-Binärpunkttypen.
Brett Caswell

54
@BKSpurgeon: Nun, nur auf die gleiche Weise, wie man sagen kann, dass alles ein Binärtyp ist, wird es zu einer ziemlich nutzlosen Definition. Dezimal ist ein Dezimaltyp, da es sich um eine Zahl handelt, die als ganzzahliger Signifikand und als Skala dargestellt wird, sodass das Ergebnis eine signifikante * 10 ^ -Skala ist, während float und double eine signifikante * 2 ^ -Skala sind. Sie nehmen eine dezimal geschriebene Zahl und verschieben den Dezimalpunkt so weit nach rechts, dass Sie eine Ganzzahl haben, um den Signifikanten und die Skala zu berechnen. Für float / double würden Sie mit einer binär geschriebenen Zahl beginnen.
Jon Skeet

21
Ein weiterer Unterschied: Float 32-Bit; doppeltes 64-Bit; und dezimale 128-Bit.
David

1073

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

65
@ Thecrocodilehunter: Entschuldigung, aber nein. Dezimal kann alle Zahlen darstellen, die in Dezimalschreibweise dargestellt werden können, jedoch nicht 1/3. 1,0 m / 3,0 m ergibt 0,33333333 ... mit einer großen, aber endlichen Anzahl von 3s am Ende. Wenn Sie es mit 3 multiplizieren, erhalten Sie keine exakte 1,0.
Erik P.

50
@ Thecrocodilehunter: Ich denke, Sie verwechseln Genauigkeit und Präzision. Sie sind in diesem Zusammenhang verschiedene Dinge. Präzision ist die Anzahl der Ziffern, die zur Darstellung einer Zahl verfügbar sind. Je präziser, desto weniger müssen Sie runden. Kein Datentyp hat eine unendliche Genauigkeit.
Igby Largeman

13
@Thecrocodilehunter: Sie gehen davon aus, dass der gemessene Wert genau ist 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 floatwird zusammenfließen 0.1und 0.1 + 1e-8, während decimalwird zusammenfließen 0.1und 0.1 + 1e-29. Sicher, innerhalb eines bestimmten Bereichs können bestimmte Werte in jedem Format ohne Genauigkeitsverlust dargestellt werden (z. B. floatkönnen beliebige Ganzzahlen bis zu 1,6e7 ohne Genauigkeitsverlust gespeichert werden) - aber das ist immer noch keine unendliche Genauigkeit.
Daniel Pryden

27
@ Thecrocodilehunter: Du hast meinen Standpunkt verfehlt. 0.1ist kein besonderer Wert ! Das einzige , was macht 0.1„besser“ als 0.10000001ist , weil Menschen wie Basis 10 und sogar mit einem floatWert, wenn man zwei Werte mit initialisieren 0.1die 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.0aber auch mit dezimalen Gleitkommazahlen (1.0 / 3) * 3 != 1.0. Weder ist vollkommen präzise.
Daniel Pryden

16
@ Thecrocodilehunter: Du verstehst immer noch nicht. Ich weiß nicht , wie dies zu sagen , nicht mehr deutlich: In C, wenn Sie double a = 0.1; double b = 0.1;dann a == b wird wahr sein . Es ist nur so , dass aund bwird 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 == bwird auch der Fall sein. Aber in diesem Fall weder von anoch bwird 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 .
Daniel Pryden

84

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:

  • Ein gewisser Genauigkeitsverlust ist in vielen wissenschaftlichen Berechnungen aufgrund der praktischen Grenzen des gemessenen physikalischen Problems oder Artefakts akzeptabel. Präzisionsverlust ist im Finanzbereich nicht akzeptabel.
  • Dezimal ist für die meisten Operationen viel (viel) langsamer als Float und Double, hauptsächlich weil Gleitkommaoperationen in Binärform ausgeführt werden, während Dezimalzahlen in Basis 10 ausgeführt werden (dh Floats und Doubles werden von der FPU-Hardware wie MMX / SSE verarbeitet während Dezimalstellen in Software berechnet werden).
  • Dezimal hat einen unannehmbar kleineren Wertebereich als doppelt, obwohl mehr Genauigkeitsziffern unterstützt werden. Daher kann Dezimal nicht verwendet werden, um viele wissenschaftliche Werte darzustellen.

5
Wenn Sie finanzielle Berechnungen durchführen, müssen Sie unbedingt Ihre eigenen Datentypen rollen oder eine gute Bibliothek finden, die genau Ihren Anforderungen entspricht. Die Genauigkeit in einem finanziellen Umfeld wird von (menschlichen) Normungsgremien definiert und sie haben sehr spezifische lokalisierte (sowohl zeitliche als auch geografische) Regeln für die Durchführung von Berechnungen. Dinge wie die korrekte Rundung werden in den einfachen numerischen Datentypen in .Net nicht erfasst. Die Fähigkeit, Berechnungen durchzuführen, ist nur ein sehr kleiner Teil des Puzzles.
James Moore

76
+---------+----------------+---------+----------+---------------------------------------------+
| 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                               |
+---------+----------------+---------+----------+---------------------------------------------+

Weitere Informationen finden Sie hier .


5
Sie haben den größten Unterschied ausgelassen, nämlich die Basis für den Dezimaltyp (Dezimalzahl wird als Basis 10 gespeichert, alle anderen aufgeführten numerischen Typen sind Basis 2).
BrainSlugs83

1
Die Wertebereiche für Single und Double sind im obigen Bild oder im Quellforum nicht korrekt dargestellt. Da wir den Text hier nicht leicht hochschreiben können, verwenden Sie das Caret-Zeichen: Single sollte 10 ^ -45 und 10 ^ 38 sein, und Double sollte 10 ^ -324 und 10 ^ 308 sein. Außerdem hat MSDN den Float mit einem Bereich von -3,4 x 10 ^ 38 bis + 3,4 x 10 ^ 38. Durchsuchen Sie MSDN nach System.Single und System.Double bei Linkänderungen. Single: msdn.microsoft.com/en-us/library/b1e65aza.aspx Double: msdn.microsoft.com/en-us/library/678hzkk9.aspx
deegee

2
Dezimal ist 128 Bit ... bedeutet, dass es 16 Bytes belegt, nicht 12
user1477332

51

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.


1
Diese Antwort gefällt mir sehr gut, besonders die Frage "Zählen oder messen wir Geld?" Abgesehen von Geld fällt mir jedoch nichts ein, was "gezählt" wird und nicht einfach eine ganze Zahl ist. Ich habe einige Anwendungen gesehen, die Dezimalstellen verwenden, nur weil double zu wenige signifikante Stellen hat. Mit anderen Worten könnte dezimal verwendet werden , da C # keinen hat vervierfachen Typen en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
John Henckel

48

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


1
@RogerLipscombe: Ich würde doublein 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 doubleals 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.
Superkatze

1
Ihre Antwort impliziert, dass Präzision der einzige Unterschied zwischen diesen Datentypen ist. Angesichts der Tatsache, dass die binäre Gleitkomma-Arithmetik normalerweise in der Hardware-FPU implementiert ist , ist die Leistung ein wesentlicher Unterschied. Dies kann für einige Anwendungen unwichtig sein, für andere jedoch von entscheidender Bedeutung.
Saille

6
@supercat double ist in Buchhaltungsanwendungen niemals geeignet. Denn Double kann nur Dezimalwerte approximieren (auch im Bereich seiner eigenen Genauigkeit). Dies liegt daran, dass double die Werte in einem Basis-2-Format (binär) speichert.
BrainSlugs83

2
@ BrainSlugs83: Die Verwendung von Gleitkommatypen zum Halten von Nicht- Ganzzahl - Mengen wäre unangemessen, aber es war historisch sehr häufig, dass Sprachen Gleitkomma-Typen haben, die genau größere Ganzzahlwerte darstellen können, als ihre Ganzzahl-Typen darstellen könnten . Das vielleicht extremste Beispiel war der Turbo-87, dessen einzige Ganzzahltypen auf -32768 bis +32767 beschränkt waren, dessen RealIIRC 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, Realeine ganze Anzahl von Pennys
darzustellen

1
... damit versucht wird, mit einer Reihe von 16-Bit-Werten eine Multi-Präzisions-Mathematik durchzuführen. Bei den meisten anderen Sprachen war der Unterschied nicht so extrem, aber seit langem ist es sehr häufig, dass Sprachen keinen ganzzahligen Typ haben, der über 4E9 hinausgeht, sondern einen doubleTyp 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 doubleeinfacher 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. ..
Supercat

36

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;

1
float.MaxValue+1 == float.MaxValuegenauso wie decimal.MaxValue+0.1D == decimal.MaxValue. Vielleicht hast du so etwas gemeint float.MaxValue*2?
Supercat

@ Supercar Aber es ist nicht wahr, dass decimal.MaxValue + 1 == decimal.MaxValue
GorkemHalulu

@ Supercar decimal.MaxValue + 0.1m == decimal.MaxValue ok
GorkemHalulu

1
Das System.Decimallö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.
Supercat

28
  1. Double und Float können sowohl bei der Kompilierung als auch zur Laufzeit ausnahmslos durch die Ganzzahl Null geteilt werden.
  2. Dezimal kann nicht durch Ganzzahl Null geteilt werden. Die Kompilierung schlägt immer fehl, wenn Sie dies tun.

6
Sie können sicher! Sie haben auch einige "magische" Werte wie Infinity, Negative Infinity und NaN (keine Zahl), die es sehr nützlich machen, vertikale Linien zu erkennen, während Steigungen berechnet werden ... Außerdem, wenn Sie sich zwischen dem Aufruf von float entscheiden müssen .TryParse, double.TryParse und decimal.TryParse (um beispielsweise festzustellen, ob eine Zeichenfolge eine Zahl ist), empfehle ich die Verwendung von double oder float, da "Infinity", "-Infinity" und "NaN" ordnungsgemäß analysiert werden , während Dezimalzahl nicht.
BrainSlugs83

Die Kompilierung schlägt nur fehl, wenn Sie versuchen, ein Literal decimaldurch 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.
Drew Noakes

@ BrainSlugs83 Je nach Kontext möchten Sie jedoch möglicherweise nicht "Infinity" oder "NaN" analysieren. Scheint ein guter Exploit für Benutzereingaben zu sein, wenn der Entwickler nicht streng genug ist.
Winter

28

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 doubleoder ein float. So was:

float myFloat;
double myDouble;

( floatsteht 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 floatSie können bis zu 7 Ziffern in Ihrer Nummer haben. Für doubles 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

floatist eine 32-Bit-Nummer und doubleeine 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!


2
Der von Ihnen erwähnte "Punkt etwas" wird allgemein als "der Bruchteil" einer Zahl bezeichnet. "Gleitkomma" bedeutet nicht "eine Zahl mit einem Punkt am Ende"; Stattdessen unterscheidet "Gleitkomma" den Typ der Zahl im Gegensatz zu einer "Festkommazahl" (die auch einen Bruchwert speichern kann). Der Unterschied besteht darin, ob die Genauigkeit fest oder schwebend ist. - Gleitkommazahlen bieten Ihnen einen viel größeren dynamischen Wertebereich (Min und Max) auf Kosten der Genauigkeit, während Festkommazahlen eine konstante Genauigkeit auf Kosten des Bereichs bieten.
BrainSlugs83

16
  • float: ± 1,5 x 10 ^ -45 bis ± 3,4 x 10 ^ 38 (~ 7 signifikante Zahlen
  • doppelt: ± 5,0 x 10 ^ -324 bis ± 1,7 x 10 ^ 308 (15-16 signifikante Zahlen)
  • dezimal: ± 1,0 x 10 ^ -28 bis ± 7,9 x 10 ^ 28 (28-29 signifikante Zahlen)

9
Der Unterschied ist mehr als nur Präzision. - decimalwird 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); decimalDarüber hinaus gibt es kein Konzept für spezielle Werte wie NaN, -0, ∞ oder -∞.
BrainSlugs83

13

Dies war ein interessanter Thread für mich, da wir heute gerade einen bösen kleinen Fehler hatten, decimalweil wir weniger Präzision als a hattenfloat .

In unserem C # -Code lesen wir numerische Werte aus einer Excel-Tabelle, konvertieren sie in eine decimalund senden sie decimaldann 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.TryParseging 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 doubleund 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 doublees weniger präzise als a ist decimal, stellte dies tatsächlich sicher, dass kleine Zahlen immer noch erkannt werden. Aus irgendeinem Grund double.TryParsewar es tatsächlich möglich, so kleine Zahlen abzurufen, während decimal.TryParsesie auf Null gesetzt würden.

Seltsam. Sehr komisch.


3
Was war aus Neugier der Rohwert von cellValue.ToString ()? Decimal.TryParse ("0.00006317592", out val) scheint zu funktionieren ...
Micahtan

11
-1 Versteh mich nicht falsch, wenn es stimmt, ist es sehr interessant, aber dies ist eine separate Frage, es ist sicherlich keine Antwort auf diese Frage.
Weston

2
Möglicherweise, weil die Excel-Zelle ein Double zurückgab und der ToString () -Wert "6.31759E-05" war, mochte die Dezimalzahl.Parse () die Notation nicht. Ich wette, wenn Sie den Rückgabewert von Decimal.TryParse () überprüft hätten, wäre er falsch gewesen.
SergioL

2
@weston Antworten ergänzen andere Antworten häufig durch das Ausfüllen von Nuancen, die sie übersehen haben. Diese Antwort zeigt einen Unterschied in Bezug auf das Parsen. Es ist sehr viel eine Antwort auf die Frage!
Robino

1
Äh ... decimal.Parse("0.00006317592")funktioniert - da ist noch etwas los. - Möglicherweise wissenschaftliche Notation?
BrainSlugs83

8

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!


Nahezu alle modernen Systeme, auch Mobiltelefone, bieten Hardware-Unterstützung für Double. und wenn Ihr Spiel sogar einfache Physik hat, werden Sie einen großen Unterschied zwischen Double und Float bemerken. (Wenn Sie beispielsweise die Geschwindigkeit / Reibung in einem einfachen Asteroids-Klon berechnen, können durch Doppelte die Beschleunigung viel flüssiger fließen als durch Schweben. - Scheint, als sollte es keine Rolle spielen, aber es ist völlig so.)
BrainSlugs83

Doubles sind auch doppelt so groß wie Floats, was bedeutet, dass Sie doppelt so viele Daten durchkauen müssen, was Ihre Cache-Leistung beeinträchtigt. Messen und verfahren Sie wie immer entsprechend.
Jojo

7

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


5

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) 

4

In einfachen Worten:

  1. Die Variablentypen Decimal, Double und Float unterscheiden sich in der Art und Weise, wie sie die Werte speichern.
  2. Präzision ist der Hauptunterschied (Beachten Sie, dass dies nicht der einfache Unterschied ist), wobei float ein Gleitkomma-Datentyp mit einfacher Genauigkeit (32 Bit) ist, double ein Gleitkomma-Datentyp mit doppelter Genauigkeit (64 Bit) und dezimal ein 128-Bit- ist Gleitkomma-Datentyp.
  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 .


Was fügt diese Antwort hinzu, das in den vorhandenen Antworten noch nicht behandelt wurde? Übrigens ist Ihr "oder" in der "Dezimal" -Zeile falsch: Der Schrägstrich auf der Webseite, von der Sie kopieren, zeigt eher eine Teilung als eine Alternative an.
Mark Dickinson

1
Und ich würde stark bestreiten, dass Präzision der Hauptunterschied ist. Der Hauptunterschied ist die Basis: Dezimaler Gleitkomma gegenüber binärem Gleitkomma. Dieser Unterschied ist Decimalfür Finanzanwendungen geeignet und das Hauptkriterium für die Entscheidung zwischen Decimalund Double. Es ist beispielsweise selten, dass DoublePräzision für wissenschaftliche Anwendungen nicht ausreicht (und für wissenschaftliche Anwendungen aufgrund ihres begrenzten Bereichs Decimaloft ungeeignet ist).
Mark Dickinson

2

Der Hauptunterschied zwischen diesen ist die Präzision.

floatist eine 32-bitZahl, doubleist eine 64-bitZahl und decimalist eine 128-bitZahl.


0
  • 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.

Decimalssind viel langsamer als ein double/float.

Decimalsund Floats/Doubleskann nicht ohne Besetzung verglichen werden, während Floatsund Doubleskann.

Decimals Erlauben Sie auch die Kodierung oder nachgestellten Nullen.


-1

So definieren Sie Dezimal, Float und Double in .Net (c #)

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.

Und die von jedem belegten Bytes sind

Float - 4
Double - 8
Decimal - 12
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.