Geldbeträge in C++
-
Hallo,
ich muss hier in einem kleinen Progrämmchen ein wenig mit Geldbeträgen rumrechnen.
Nun wollte ich mal fragen, wie ihr da in der Regel vorgeht?
Was verwendet ihr?
1. Einen simplen floating-point-Typ (z.B. double) + Ignorieren der möglicherweise auftretenden Genauigkeitsprobleme.
2. Einen (großen) integralen Typen (z.B. long oder besser long long) + Multiplikation mit 100 (oder 1000 oder was auch immer die kleinste Einheit der Währung für eine Größenordnung hat)
3. Eine Currency oder Money-Klasse.
4. Eine allgemeine Fixed-Decimal-Klasse.
5. Etwas ganz anderes.Kennt jemand hübsche und freie C++ Money-Klassen?
-
Keine Ahnung wie "richtig" das ist...
Ich verwende long double. Intern speichere ich alles in Euro, umgerechnet wird nur bei Bedarf.
Wenn ich das Zeug in eine Datenbank schreibe verwende ich decimal, weil der SQL-"Standard" hier im Gegensatz zu z.B. float vorschreibt dass dann richtig gerechnet wird.
Einige Rechenzentren verwenden auch einen Ganzzahlentyp und arbeiten mit Cent anstatt Euro.
-
Wenn ich das Zeug in eine Datenbank schreibe verwende ich decimal, weil der SQL-"Standard" hier im Gegensatz zu z.B. float vorschreibt dass dann richtig gerechnet wird.
In der Datenbank habe ich auch decimal. Probleme bereitet mir nur der Übergang zwischen Datenbank und Anwendung.
Hattest du mit long double denn schonmal probleme? Ich kenne mich mit dem Thema nicht so aus. Habe nur schon oft gelesen, dass man Aufgrund der auftretenden Rundungsfehler für die Manipulation von Geldbeträgen besser keine floating-Point-Zahlen verwenden sollte. Zumindest nicht, wenn man direkt mit Euro.Cent (oder Dollar.Cent oder...) rechnet.
-
Hi,
also in unserem Warenwirtschaftssystem nutzen wir einen 64bit Datentyp.
Ich muss da nochmal meinen Ausbilder fragen, falls es dich interessiert, wie genau
wir da vorgehen. Ich weiss noch, dass wir so gut wei keine Genauigkeitsprobleme haben und dass
wir Funktionen aus der GNU C Library nutzen (ist aber soweit ich weiss nicht in Standard C
enthalten).Von der nutzen wir Funktionen wie bdiv (binaere division), bmul (binaere multiplikation) usw.
Ich werd morgen nochmal nachfragen, oder nachher, falls er heute nochmal in die Firma kommt.
mfg
v R
-
1. Einen simplen floating-point-Typ (z.B. double) + Ignorieren der möglicherweise auftretenden Genauigkeitsprobleme.
vorteile: einfach
nachteile: rundungsfehler nicht verbuchbar
vermeidbar sind sie nicht, egal was die wissenschaftler da behaupten.2. Einen (großen) integralen Typen (z.B. long oder besser long long) + Multiplikation mit 100 (oder 1000 oder was auch immer die kleinste Einheit der Währung für eine Größenordnung hat)
millicent sind bei banken, vermute ich.
64 bits wohl.
vorteil: auch nicht so gewaltig schwer, und sogar handhabbar, wenn man nie währungen mit währungen multipliziert.
nachteil: zu lächerlich, sowas nicht in ne klasse zu stecken. fixpunktarithmetik verlangt disziplin vom anwender.3. Eine Currency oder Money-Klasse.
na, logo.
4. Eine allgemeine Fixed-Decimal-Klasse.
kostet kaum mehr, ne allgemeine drunterzuschrauben.
5. Etwas ganz anderes.
typedef double Geldbetrag;
natürlich.
bei bedarf wird später die Klasse gebastelt. aber erst, wenn klar ist, daß die rundungsfehler überhaupt jemanden jucken.
ach, wozu ne viertel stunde arbeit hinausschieben. ich würd gleich nen 64-bitter als attribut der währungsklasse nehmen.frage: ich Währung eigentlich das gute Wort, wenn man einen Geldbetrag beschreiben will? Klingt für mich wie Lägeneinheit als Klassenname für Längen.
-
Hallo,
soweit schonmal danke für die Antworten.volkard schrieb:
1. Einen simplen floating-point-Typ (z.B. double) + Ignorieren der möglicherweise auftretenden Genauigkeitsprobleme.
vorteile: einfach
nachteile: rundungsfehler nicht verbuchbar
vermeidbar sind sie nicht, egal was die wissenschaftler da behaupten.Was bedeutet dieses "nicht verbuchbar"?
volkard schrieb:
3. Eine Currency oder Money-Klasse.
na, logo.
Doch woher nehmen. Selbstschreiben traue ich mir ehrlich gesagt nicht zu.
volkard schrieb:
frage: ich Währung eigentlich das gute Wort, wenn man einen Geldbetrag beschreiben will? Klingt für mich wie Lägeneinheit als Klassenname für Längen.
Nein. Currency beschreibt in der Tat nicht das, was ich brauche. Ich habe ja nur eine Währung.
Money ist definitv besser. Ich kenne mich in der Geldwelt nicht so aus und verwechsle deshalb recht häufig die Bedeutungen von Currency, Money und Monetary.Ich werd morgen nochmal nachfragen, oder nachher, falls er heute nochmal in die Firma kommt.
Danke fein.
-
[quote="HumeSikkins"]Doch woher nehmen. Selbstschreiben traue ich mir ehrlich gesagt nicht zu./quote]
Wieso nicht?
Du fängst einfach mit einer Klasse an, die hat intern einen long long auf Cent-Basis. Dem Ding verpasst Du sämtliche Operatoren und Kombinationen für + und -, sowie die ganzen == != <= Sachen.
Außerdem Methoden zum Setzen und Lesen des Wertes in der Recheneinheit (hier Euro). Dann noch was, um die Darstellung in einen String zu streamen (also so mit Formatierung und Co).
Intern speicherst Du noch den Umrechnungsfaktor von Recheneinheit (Euro) in Basiseinheit (Cent), hier also 100, und das Symbol für die Recheneinheit.
Außerdem implementierst Du alle Methoden für Rechenoperationen so, daß sie eine Exception werfen, wenn der String für die Recheneinheit der beiden Objekte nicht übereinstimmt (d.h. Euro + Pfund ist verboten). Das ist für den Anfang schon mal ganz gut.
Mehr implementierst Du dann, wenn Du es für das Programm brauchst. Und vorher denkst Du auch noch nicht darüber nach.
Aber damit läßt sich schon ein Konto mit Zu- und Abgängen realisieren. Zinsen sind halt noch nicht enthalten... weiß ja nicht ob Du das brauchst.
-
Hi,
also ich hab jetzt nochmal nachgefragt und wir gehen folgendermassen vor:
Wir haben einen struct definiert, mit zwei 32bit-Elementen:
typedef struct { LongWord left,right; }bit64;
LongWord ist so definiert 'typedef unsigned LongWord;'
Desweiteren haben wir einen struct definiert, mit vier 32bit-Elementen, falls zwei
64bit Zahlen addiert werden (es koennte ja ein groesseres Ergebnis herauskommen).Dann nutzen wir die schon o. g. bxxx-Funktionen, um mit den 64bit-Werten zu rechnen
und haben 2 Funktionen str2bin bzw. bin2str um Waehrungen, welche als c-String vorliegen
entsprechend umzurechnen.Ich muss mich an dieser Stelle noch meinen ersten Beitrag korrigieren, so wie es ausschaut,
sind diese Funktionen nicht aus der GNU C-Library, sondern aus der GNU MP Library
(http://www.swox.com/gmp/).Ich muss zugeben, dass ich durch die Funktionen nicht so recht durchsteige, allerdings hab
ich mich mit diesen Funktionen auch noch nicht wirklich befasst, da ich sie per c&p in unser
Warenwirtschaftssystem (das neue) uebernehmen konnte. Da die Funktionen oeffentlich
zugaenglich sind (also nicht von uns stammen), kann ich dir gerne diese nach rafb.net
posten oder per Mail zuschicken, wenn du daran interessiert bist.mfg
v R
-
Dieses bit64 ist dann ja nichts anderes als unsigned long long?
-
Das ist richtig, aber im Speicher liegen sie hintereinander und ergeben einen 64bit-Wert.
mfg
v R