Autor |
Beitrag |
baka0815
      
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Mi 22.08.12 14:24
Hallo zusammen,
bei einem Projekt muss ich Währungen umrechnen (z.B. EUR in USD) und habe dafür bisher immer den Datentyp Currency verwendet. Dies hat bisher auch problemlos funktioniert, allerdings sollen nun Wechselkurse mit mehr als 4 Nachkommastellen verwendet werden.
Da dies per Currency nicht möglich ist und ich per Suche (vermutlich die falschen Suchbegriffe?) nichts gefunden habe, stelle ich die Frage hier an euch.
Double möchte ich wegen der Fließkommaungenauigkeit ungerne verwenden, da es sich hier um Geldbeträge handelt.
|
|
Delphi-Laie
      
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Mi 22.08.12 14:34
Extended?
Oder einen selbstdefinierten Datentyp, der den Nachkommaanteil beinihaltet oder gar mit Brüchen (=nicht ausgeführte Dvisionen) intern operiert, verwenden. Units dazu müßte es einige geben.
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mi 22.08.12 14:40
Wie groß können die Beträge werden?
Double hätte 17 Stellen, das wären bei 1 Mrd. "Geld" noch 7 Stellen hinter dem Komma. Extended wären 19 Stellen.
Grade drüber gestolpert: " Decimals"
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
baka0815 
      
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Mi 22.08.12 16:18
1 Mrd. müsste eigentlich reichen, nur hatte ich schon Probleme, dass einstellige Währungskurse (1,1243435) hinter dem Komma abwichen.
Wenn ich den Betrag als Currency verwende, kann ich dann Double für den Kurs nehmen? Würde das "reichen"?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var EUR, USD: Curreny; Kurs: Double; begin USD := 100.00; Kurs := 0.80375; EUR := USD * Kurs; end; |
Ist so denn sichergestellt, dass ich an der fünften Stelle keine Fließkommaungenauigkeit habe? Wenn ich hier einen Kurs von 0,80374 raus bekäme, hätte ich nachher eine Cent-Differenz.
|
|
Lemmy
      
Beiträge: 792
Erhaltene Danke: 49
Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
|
Verfasst: Mi 22.08.12 16:43
Hallo,
Double/Extended und Sicher sind Dinge die sich ausschließen!
Um bei deinem Beispiel zu bleiben:
1.000.000.000,00 € d.h. der zehntel cent muss sicher sein, d.h. bei 2 Berechnungen darf es da keinen Unterschied geben. Somit muss dein Faktor mit dem du multiplizierst/dividierst auf 12 Stellen nach dem Komma 100% stimmen. Da bleibt dir nur der Einsatz einer entsprechenden lib mit der Du solche Zahlen abbilden kannst.
Was mich aber etwas irritiert ist, warum brauchst Du mehr als 4 Stellen nach dem Komma für den Währungskurs? Ich habe bisher in den Finanzportalen max. 4 Stellen gesehen.
|
|
baka0815 
      
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Mi 22.08.12 17:23
Es kommt drauf an, wie rum man rechnet.
EUR -> USD ist ein Kurs von 1,2441 (4 Stellen)
USD -> EUR ist ein Kurs von 0,80375 (5 Stellen)
Außerdem darf ein Betrieb für die interne Kostentrechnung einen abweichenden Umrechnungskurs selbst festlegen...
|
|
GuaAck
      
Beiträge: 378
Erhaltene Danke: 32
Windows 8.1
Delphi 10.4 Comm. Edition
|
Verfasst: Do 23.08.12 23:44
Hallo,
a) Man sollte nicht jeden Unsinn programmieren, sondern durchaus kritisch nach dem Sinn fragen. Welche Börse stellt denn Wechselkurse so genau bereit?
b) Currency reicht bis knapp 10^14, da kann man also den Staatshaushalt der USA (2,5*10^12 $) noch in Cent ausdrücken. Also warum nicht einfach die Währungen individuell skalieren, z. B. in Cent rechnen? Bezüglich kleiner gestückelter Währungseinheiten (z. B. JPY, Japanischer Yen, 1 YEN in der Größenordnung 0,01 EUR ) reichen 6 Nachkommastellen ohnehin nicht aus und man gibt den Kurs besser z. B. per 1000 Einheiten an.
Gruß
GuaAck
|
|
baka0815 
      
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Mo 27.08.12 15:04
Das Programm rechnet mit Gehältern und da kann ich nicht die ganze Rechnung einfach umstellen. Hier geht es dann auch um die Steuer- und SV-Abgaben.
Unser Programm rechnet immer in EUR, allerdings haben einige Kunden ein paar Spezialitäten, indem hier dann tatsächlich so getan wird, als wäre EUR = USD und dann muss nicht mehr von EUR in USD, sondern eben von USD in EUR umgerechnet werden.
Das ist auch eine Konstellation aus der ich nicht raus komme, egal was für bessere Möglichkeiten es hier geben mag...
|
|
Gammatester
      
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Mo 27.08.12 16:29
Die Rechnungen sind doch mehr oder weniger trivial - notfalls wird mit millionstel Einheiten gearbeitet, der Kurs ist ein Bruch a/b mit relativ kleinen ganzen Zahlen, d.h. int64 sollte locker reichen: Ex = (Ux*a) div b, Ex, Ux in millionstel oder milliardstel Einheiten. Die interessante Frage ist: wie soll/muß gerundet werden? Man sieht's ja schon daran, daß 1 Dollar = 0.80375 Euro seit soll, selbst bei einer Verrechnungseinheit von 1/100-Cent muß klar sein, ob das 80.37 oder 80.38 Euro-Cent sein sollen. Also bleibt zu klären:
- was ist die Verechnungseinheit (1/100-Cent?)
- wie soll gerundet werden (abschneiden, aufrunden, kaufmännisch? -> Rundung)
Gruß Gammmatester
|
|
knittel
      
Beiträge: 71
Erhaltene Danke: 2
Win XP, Win7, openSUSE
Delphi 7
|
Verfasst: Mo 27.08.12 18:47
Immer wenn es um Variablen-Typen geht kann ich nur folgende Seite empfehlen:
www.delphibasics.co....cle.asp?Name=Numbers
Du kannst ja ohne Probleme Currencies mit Doubles oder Extendeds verrechnen um die Durchführung kümnmert sich ja glücklicherweise Delphi.
Daher Currency's für bisheriges behalten und mit double/extended/single die Wechselkurse (gleiche Art der Speicherungsform nur mit unterschiedlicher Genauigkeit)
_________________ "Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
|
|
Gammatester
      
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Di 28.08.12 09:01
Scheint mir allerdings nicht sehr vertrauenswürdig: "Currency 8 50+ significant digits, fixed 4 decimal places". Wie man in die 64-Bit von Currency mehr als 50 Dezimalstellen unterbringen will, ist mir völlig schleierhaft! Dafür darf's bei double offenbar etwas weniger sein: Angeblich 15 Stellen, dabei ist für double ulp(1) = 1.11e-16 (ulp=unit in last place).
Weiter: "Exp Gives the exponent of a number", der Author kann offensichtlich nicht die Exponentialfunktion vom Logarithmus unterscheiden!
Im übrigen lösen die ganzen Verweise die ursprüngliche Aufgabe nicht nicht, deren "Schwierigkeit" im wesentlichen aus Wandlungs- und Rundungseigenarten resultieren.
|
|
baka0815 
      
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Di 28.08.12 10:30
Gerundet werden muss immer Kaufmännisch.
Dass man Cent nicht mit mehr als zwei Nachkommastellen auszahlen kann ist ja völlig klar.
Was ich eben vermeiden möchte sind Cent-Differenzen aufgrund Fließkommaungenauigkeiten.
|
|
DonManfred
      
Beiträge: 148
Erhaltene Danke: 2
Windows 7
Delphi XE3 Pro + HTML5Builder
|
Verfasst: Di 28.08.12 10:50
Sorry, couldn´t resist...
baka0815 hat folgendes geschrieben : | Gerundet werden muss immer Kaufmännisch.
Dass man Cent nicht mit mehr als zwei Nachkommastellen auszahlen kann ist ja völlig klar. |
Wie schafft du es denn CENT mit zwei Nachkommastellen auszuzahlen?
Ein Kunde bekommt, z.B., 5,25 CENT zurück. Du hast ne Schneidemachine an der Kasse? 
_________________ Gruss Manfred
|
|
Gammatester
      
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Di 28.08.12 11:09
|
|
baka0815 
      
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Di 28.08.12 13:22
Ich hatte gehofft, die Berechnungen, die das Programm eh schon macht (Betrag * Kurs bzw. Betrag / Kurs) einfach beibehalten zu können.
Die Kurse sind auch in der DB gespeichert und dort bekomme ich sie ja eh nur per AsCurrency oder per AsFloat raus, wie ich gerade festgestellt habe.
Dann müsste ich die Werte auch mit hundert multipliziert in der DB speichern um weiter mit Currency rechnen zu können (Wert * Query.FieldByName(Kurs).AsCurrency / 100). Das wiederum ist eine größere Änderung, die sich dasnn komplett durchzieht... -_-°
|
|