Warum ist die Verwendung eines NICHT-dezimalen Datentyps schlecht für Geld?

8

tl; dr: Was ist los mit meiner Cur (Währung) Struktur?

tl; dr 2: Bitte lesen Sie den Rest der Frage, bevor Sie ein Beispiel mit float oder double geben. : -)

Ich bin mir bewusst, dass diese Frage schon viele Male im Internet auftaucht, aber Ich habe noch keine überzeugende Antwort gefunden , also dachte ich, ich würde nochmal fragen.

>

Ich verstehe nicht, warum die Verwendung eines nicht-dezimalen Datentyps schlecht für den Umgang mit Geld ist. (Dies bezieht sich auf Datentypen, die Binärziffern statt Dezimalziffern speichern.)

Wahr, es ist nicht ratsam, zwei double s mit a == b zu vergleichen. Aber Sie können einfach a - b <= EPSILON oder etwas ähnliches sagen.

Was ist falsch an diesem Ansatz?

Zum Beispiel habe ich gerade ein struct in C # gemacht, von dem ich glaube, dass es Geld korrekt behandelt, ohne irgendwelche dezimalen Datenformate zu verwenden:

%Vor%

(Sorry für das Ändern des Namens Currency in Cur , für die schlechten Variablennamen, für das Weglassen von public und für das schlechte Layout; Ich habe versucht, alles auf den Bildschirm zu bringen, so dass Sie lesen konnten es ohne Scrollen.):)

Sie können es verwenden wie:

%Vor%

Natürlich hat C # den Datentyp decimal , aber das ist neben dem Punkt hier - die Frage ist, warum das oben genannte gefährlich ist, nicht warum wir decimal nicht verwenden sollten.

Würde es jemandem etwas ausmachen, mir ein Gegenbeispiel einer gefährlichen Aussage zu liefern, das in C # fehlschlagen würde? Ich kann mir keine vorstellen.

Danke!

Hinweis: Ich bin nicht darüber, ob decimal eine gute Wahl ist. Ich frage, warum ein binärbasiertes System als unangemessen bezeichnet wird.

    
Mehrdad 24.04.2011, 05:19
quelle

5 Antworten

10

Floats sind nicht stabil zum Akkumulieren und Dekrementieren von Fonds. Hier ist Ihr aktuelles Beispiel:

%Vor%

Auf meiner Box gibt es $ 4.000.002.000.0203 angesammelt vs. 4000002000 erwartet in C #. Es ist ein schlechter Deal, wenn er bei vielen Transaktionen in einer Bank verloren geht - es müssen nicht große, sondern viele sein. Hilft das?

    
J Trana 24.04.2011, 05:46
quelle
4

Normalerweise erfordern monetäre Berechnungen genaue Ergebnisse, nicht nur genaue Ergebnisse. Die Typen float und double können nicht den gesamten Bereich der reellen Zahlen der Basis 10 genau darstellen. Zum Beispiel kann 0.1 nicht durch eine Gleitkommavariable dargestellt werden. Was gespeichert wird, ist der nächstgelegene darstellbare Wert, der eine Zahl wie 0,0999999999999999996 sein kann. Probieren Sie es selbst aus, indem Sie Ihre Struktur testen, zum Beispiel versuchen Sie 2.00 - 1.10 .

    
Legs 24.04.2011 05:41
quelle
4

Ich bin mir nicht sicher, warum Sie die Antwort von J Trana als irrelevant abtun. Warum versuchst du es nicht selbst? Dasselbe Beispiel funktioniert auch mit Ihrer Struktur. Sie müssen nur ein paar zusätzliche Iterationen hinzufügen, da Sie ein Double anstelle eines Floats verwenden, was Ihnen ein bisschen mehr Präzision gibt. Verzögert das Problem nur, wird es nicht los.

Beweis:

%Vor%

Ergebnis:

%Vor%

Wir sind nur bis zu 0,08 Cent, aber das wird sich letztendlich summieren.

Ihre Änderung:

%Vor%

Druckt $ 0.

    
mpen 24.04.2011 06:08
quelle
2
Mehrdad, ich glaube nicht, dass ich dich überzeugen könnte, wenn ich die gesamte SEC einbringen würde. Nun implementiert die gesamte Klasse BigInteger-Arithmetik mit einer impliziten Verschiebung von 2 Dezimalstellen. (Es sollte mindestens 4 für buchhalterische Zwecke sein, aber wir können 2 bis 4 leicht genug ändern.)

Was Vorteil haben wir diese Klasse mit Double anstelle von BigDecimal (oder LongLong, wenn so etwas verfügbar ist)? Für den Vorteil eines primitiven Typs bezahle ich mit teuren Rundungsoperationen. Und ich bezahle auch mit Ungenauigkeiten. [Beispiel von hier 1 ]

%Vor%

OK, hier haben wir mit einem Float anstatt mit einem Double gesichert, aber sollte das nicht eine große Warnflagge sein, dass das ganze Konzept falsch ist und dass wir in Schwierigkeiten geraten könnten, wenn wir Millionen von Berechnungen machen müssten? p>

Jeder Finanzfachmann glaubt, dass die Gleitkommadarstellung von Geld eine schlechte Idee ist. (Siehe, unter Dutzenden von Hits, Ссылка .) Was ist wahrscheinlicher: Sie sind alle dumm oder Floating-Point-Geld ist tatsächlich eine schlechte Idee?

    
Andrew Lazarus 24.04.2011 06:03
quelle
0
%Vor%

Das Problem ist, dass 0.00015 in binary wirklich 0,00014999999999999988685946966947568625982967205345630645751953125 ist, was down abrundet, aber der exakte Dezimalwert rundet nach oben .

    
dan04 24.04.2011 06:03
quelle

Tags und Links