| 

.NET C# Java Javascript Exception

1
Ich muss aufwendigen Berechnungen mit Geldbeträgen durchführen. Habe mir dazu eine Wrapper Klasse für Geldbeträge geschrieben, in der der jeweilige Geldwert in einer primitiven double Member-Variablen hinterlegt wird.

Ich überlege jetzt diese Geld Wrapper Klasse derart zu optimieren, dass der Geldbetrag intern einen primitiven IntegerTyp bekommt und die Dezimalposition in einer extra Member-Variablen gespeichert wird.

Hat jemand mit dieser Problemstellung Erfahrung? Bringt das überhaupt Vorteile in der Performance oder Genauigkeit, wenn eh nur zum Schluss auf Cent genau (2 Dezimalstellen) gerundet wird?
01.12.2013
mobidat 63 1 7
Ich habe deinen Edit eben erst gesehen und meine Antwort bzgl. Genauigkeit entsprechende ausführlicher formuliert.
phg 02.12.2013
1 Antwort
1
Also ich würde bei Geldbeträgen immer mit Ganzzahl-Typen arbeiten, da bei Gleitkomma-Typen Rundungsfehler recht böse zuschlagen können.

Ein Beispiel: 9.99 + 20 = 29.990000000000002 nicht nur in Java (natürlich mit Gleitkomma-Typen)

Wenn jetzt mit diesen Zahlen weiter gerechnet wird, dann steigern sich die Rundungsfehler relativ schnell auf Abweichungen bei der 1. bzw. 2. Nachkommastelle. Bei einer einfachen Berechnung (Einkaufspreis + Marge) * MwSt. hatte ich teilweise schon einen Fehler von 10 Cent! Bei Integer-Berechnungen entfallen schon mal die Fehler, welche durch die Binär-Repräsentation der Gleitkomma-Zahlen entstehen können und es sollten nur bei Division überhaupt Rundungsfehler auftreten.

Wenn intern mit mehr Nachkommastellen gerechnet wird, als dann eigentlich verwendet werden (z.B. mit 3 NK statt den 2 NK die du dann anzeigen möchtest) lässt sich bei der Ausgabe der Zahlen wesentlich genauer runden.

Normalerweise verwende ich keine variable Dezimalposition, sondern legen diese einfach auf 3/4/5/... Nachkommastellen in einer Konstanten fest (Faustregel: InternVerwendeteNachkommastellenDesKunden + 2) aber dein dynamischer Ansatz sollte auch funktionieren. Wäre aber etwas mehr Aufwand beim Implementieren und erfordert mehr Sorgfalt beim verwenden deiner Klasse. Falls es keinen guten Grund für eine dynamische Dezimalposition gibt würde ich das lassen.

Was die Performance betrifft; Integer-Operationen sind auf normalen CPUs wesentlich schneller als Gleitkomma-Operationen. Bei modernen CPUs halte ich das aber bis zu einer gewissen (recht hohen) Grenze für vernachlässigbar. Wenn dich das für deinen konkreten Anwendungsfall interessiert, dann müsstest du das mal selber messen.
01.12.2013
phg 1,6k 3
Danke PHG für die sehr ausführliche Antwort! ich habe inzwischen unter dem Begriff "Money Pattern" viele interessante Ansätze zum Thema "Geld" - Infrastruktur erfahren. Viele Beispiele verwenden BigDecimal oder BigInteger (java.math) als internen Speicher für höhere Genauigkeit bei Zinsberechnungen. Ein großer Nachteil ist aber Unveränderbarkeit der Big-Objekte. Das kann bei sehr vielen Buchungen m.E. zur "Speicherexplosion" führen. Auch die Performance könnte durch die zusätzliche Kapselung der Geldbeträge in Big-Objekte leiden.
mobidat 03.12.2013
@mobidat: Schreib doch einen Test, der Deine Performanceanforderungen prüft. Das hat zudem den Vorteil, dass Du mit einem Profiler gezielt nachvollziehen kannst, wo der Flaschenhals ist. Ich kann Dir nicht sagen, wie oft ich schon ungläubig vor dem Profiler gesessen bin. Performance ist keine "Gefühlssache", da zählen nur harte Fakten.
ffordermaier 03.12.2013
@mobidat: Unveränderbarkeit ist bei Datentypen meist sehr wünschenswert. Nicht umsonst sind die eingebauten Datentypen, allen voran String, unveränderbar. Objekte erzeugen ist in Java eigentlich eine ziemlich billige Operation, und das Aufräumen zumindest mal dann, wenn sie nicht lange leben. Ansonsten kann ich dem Kommentar von @ffordermaier nur beipflichten.
Matthias Hlawatsch 03.12.2013
Ich würde mir da keine Gedanken über den Speicherverbrauch machen, wenn Du mit so großen Geld-Beträgen rechnen musst, dann sollte der extra RAM aus der Portokasse bezahlbar sein ;)

Was Performance (und auch Speicherverbrauch) betrifft kannst Du erst eine Aussage treffen, wenn Du entsprechende Messungen gemacht hast, wie ffordermaier schon empfohlen hat.

Erfahrungsgemäß optimiert man eh fast immer an der falschen Stelle, solange man keine Messwerte hat.
phg 03.12.2013

Stelle deine Java-Frage jetzt!