Ich sage immer in c #, dass eine Variable vom Typ double nicht für Geld geeignet ist. Alle seltsamen Dinge könnten passieren. Aber ich kann anscheinend kein Beispiel erstellen, um einige dieser Probleme zu demonstrieren. Kann jemand ein solches Beispiel geben?
(Bearbeiten; dieser Beitrag wurde ursprünglich mit C # markiert; einige Antworten beziehen sich auf bestimmte Details von decimal
, was daher bedeutet System.Decimal
).
(Bearbeiten 2: Ich habe speziell nach C # -Code gefragt, daher denke ich nicht, dass dies nur sprachunabhängig ist.)
c#
language-agnostic
decimal
currency
Doekman
quelle
quelle
Antworten:
Sehr, sehr ungeeignet. Verwenden Sie eine Dezimalstelle.
double x = 3.65, y = 0.05, z = 3.7; Console.WriteLine((x + y) == z); // false
(Beispiel von Jons Seite hier - empfohlene Lektüre ;-p)
quelle
Sie erhalten ungerade Fehler, die effektiv durch Rundungen verursacht werden. Darüber hinaus sind Vergleiche mit exakten Werten äußerst schwierig - normalerweise müssen Sie eine Art Epsilon anwenden, um zu überprüfen, ob der tatsächliche Wert "nahe" an einem bestimmten Wert liegt.
Hier ist ein konkretes Beispiel:
using System; class Test { static void Main() { double x = 0.1; double y = x + x + x; Console.WriteLine(y == 0.3); // Prints False } }
quelle
Ja, es ist ungeeignet.
Wenn ich mich richtig erinnere, hat double ungefähr 17 signifikante Zahlen, so dass Rundungsfehler normalerweise weit hinter dem Dezimalpunkt auftreten. Die meisten Finanzsoftware verwendet 4 Dezimalstellen hinter dem Dezimalpunkt, sodass 13 Dezimalstellen zur Verfügung stehen, sodass die maximale Anzahl, mit der Sie für einzelne Operationen arbeiten können, immer noch sehr viel höher ist als die Staatsverschuldung der USA. Rundungsfehler summieren sich jedoch mit der Zeit. Wenn Ihre Software längere Zeit läuft, verlieren Sie möglicherweise Cent. Bestimmte Operationen werden dies noch schlimmer machen. Zum Beispiel führt das Hinzufügen großer Mengen zu kleinen Mengen zu einem erheblichen Genauigkeitsverlust.
Sie benötigen Festkomma-Datentypen für Geldoperationen. Den meisten Menschen macht es nichts aus, wenn Sie hier und da einen Cent verlieren, aber Buchhalter sind nicht wie die meisten Menschen.
Bearbeiten
Laut dieser Website http://msdn.microsoft.com/en-us/library/678hzkk9.aspx Doppel haben tatsächlich 15 bis 16 signifikante Ziffern anstelle von 17.
@ Jon Skeet Dezimalzahl ist aufgrund ihrer höheren Genauigkeit, 28 oder 29 signifikanten Dezimalstellen, besser geeignet als doppelt. Dies bedeutet eine geringere Wahrscheinlichkeit, dass akkumulierte Rundungsfehler signifikant werden. Festkomma-Datentypen (dh Ganzzahlen, die Cent oder 100stel Cent darstellen, wie ich sie verwendet habe) wie Boojum-Erwähnungen sind tatsächlich besser geeignet.
quelle
decimal
der Ausdruckx + 1 != x
ist immer wahr. Außerdem bleibt die Präzision erhalten, sodass Sie den Unterschied zwischen1
und erkennen können1.0
.Decimal
Wert kann rechts vom Dezimalpunkt an Genauigkeit verlieren, ohne dass ein Problem angezeigt wird.double
hat 15,9 signifikante Dezimalstellen, die nur ganzzahlige Werte berücksichtigen. Die Situation nach dem Dezimalpunkt ist wertabhängig.Da
decimal
ein Skalierungsfaktor von Vielfachen von 10 verwendet wird, können Zahlen wie 0,1 genau dargestellt werden. Im Wesentlichen repräsentiert der Dezimaltypdouble
dies als 1/2 ^ 1, während a dies als 104857/2 ^ 20 darstellen würde (in Wirklichkeit wäre es eher eine wirklich große Zahl / 2 ^ 1023).A
decimal
kann jeden beliebigen Basis-10-Wert mit bis zu 28/29 signifikanten Stellen (wie 0,1) genau darstellen. Adouble
kann nicht.quelle
Mein Verständnis ist, dass die meisten Finanzsysteme Währung mit ganzen Zahlen ausdrücken - dh alles in Cent zählen.
Die doppelte IEEE-Genauigkeit kann tatsächlich alle ganzen Zahlen genau im Bereich von -2 ^ 53 bis + 2 ^ 53 darstellen. (Hacker's Delight, S. 262) Wenn Sie nur Addition, Subtraktion und Multiplikation verwenden und alles auf ganze Zahlen innerhalb dieses Bereichs beschränken, sollten Sie keinen Genauigkeitsverlust feststellen. Ich wäre jedoch sehr vorsichtig bei Teilungen oder komplexeren Operationen.
quelle
double
jedoch keinen 64-Bit-Integer-Typ. Ich würde vorschlagen, dass die Durchführung von Berechnungen alsdouble
, skaliert, dass jede semantisch erforderliche Rundung immer auf ganze Einheiten erfolgt, der effizienteste Ansatz ist.Die Verwendung von double ist ungeeignet, wenn Sie nicht wissen, was Sie tun.
"doppelt" kann einen Betrag von einer Billion Dollar mit einem Fehler von 1/90 Cent darstellen. So erhalten Sie hochpräzise Ergebnisse. Möchten Sie berechnen, wie viel es kostet, einen Mann auf den Mars zu bringen und ihn wieder lebendig zu machen? Double reicht völlig aus.
Aber mit Geld gibt es oft sehr spezifische Regeln, die besagen, dass eine bestimmte Berechnung ein bestimmtes Ergebnis liefern muss und kein anderes. Wenn Sie einen Betrag berechnen, der sehr, sehr nahe an 98,135 USD liegt, gibt es häufig eine Regel, die bestimmt, ob das Ergebnis 98,14 USD oder 98,13 USD betragen soll. Sie müssen diese Regel befolgen und das erforderliche Ergebnis erhalten.
Je nachdem, wo Sie leben, funktioniert die Verwendung von 64-Bit-Ganzzahlen zur Darstellung von Cent, Pennies oder Kopeken oder der kleinsten Einheit in Ihrem Land normalerweise einwandfrei. Beispielsweise können 64-Bit-Ganzzahlen mit Vorzeichen, die Cent darstellen, Werte bis zu 92.223 Billionen Dollar darstellen. 32-Bit-Ganzzahlen sind normalerweise ungeeignet.
quelle
Nein, ein Double hat immer Rundungsfehler. Verwenden Sie "Dezimal", wenn Sie auf .Net ...
quelle
Tatsächlich ist Gleitkomma- Double perfekt geeignet, um Geldbeträge darzustellen, solange Sie eine geeignete Einheit auswählen.
Siehe http://www.idinews.com/moneyRep.html
Ist also Fixpunkt lang . Entweder verbraucht es 8 Bytes, sicherlich besser als die 16, die von einem Dezimalelement verbraucht werden .
Ob etwas funktioniert oder nicht (dh das erwartete und korrekte Ergebnis liefert), ist weder eine Frage der Abstimmung noch der individuellen Präferenz. Eine Technik funktioniert entweder oder nicht.
quelle