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:
(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.
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?
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
.
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.
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?