Währung, Geld und der ganze Rest
Matthias Claudius hat "Wenn jemand eine Reise tut, so kann er was erzählen." geschrieben und noch heute ist das ein oft zitierter Satz. Wer eine Reise tut, hat aber auch oft mit fremden Sprachen, Gesetzen und vorallem mit anderen Währungen zu tun. Kommen dann noch gänzlich andere Längen- und Volumeneinheiten hinzu, wird es richtig spannend. Wollen wir während eines USA Aufenthaltes die Kosten eines Trips ermitteln, müssen wir nicht nur Dollar in Euro umrechnen, wir müssen auch noch Miles in km und Gallone in Liter umrechnen. Aber fangen wir von vorne an.
Unter einer Währung versteht man im weitesten Sinne das Geldwesens eines Staates. Der Währungsraum ist dabei der Geltungsbereich der Währung. Sie ermöglicht den Transfer von Waren und Dienstleistungen.
Aktuell gibt es weltweit mehr als 180 Währungen. Eine Liste mit den vorhandenen Währungen ist in ISO 4217 zu finden.
Wenn man nun eine Reise tut, und mit Hilfe von PHP die Reisekosten ausrechnen will, so kann man das auf unterschiedlichen Wegen tun.
Geldbeträge in PHP abbilden
In PHP gibt es mehrere Möglichkeiten Geldbeträge direkt darzustellen und zu verarbeiten. Man kann zum Beispiel Geldbeträge folgendermaßen abbilden:
Diese Methoden haben alle ihre eigenen Nachteile. So muss man bei der Verwendung von float
mit Rundungsfehlern kämpfen und bei Verwendung von Integern muss man die Anzahl der Stellen als eigenständigen Wert speichern.
$money=1000; // 10 €
$currency="EUR"; // Währung
$unit=2; // Stellen hinter dem Komma
Arbeiten mit dem Alvine PHP-Framework
Wir haben uns dafür entschieden eine eigene Implementierung für Geldbeträge und Währungen in unserem PHP-Framework aufzunehmen. Unterhalb des Namespaces \Alvine\Measure\Economics
finden sich die Money- und Currency-Klasse des Frameworks. In dem UML-Diagramm sind zwei exemplarische Klassen angegeben. Tatsächlich verfügt das Framework über Klassen für jede in ISO 4217 definierte Währung.
Randnotiz: Die Dokumentation zum PHP-Framework befindet sich hier. Das Framework kann auf der Downloadseite heruntergeladen werden.
Wie man erkennt, ist die Money-Klasse von der \Alvine\Measure\Amount
Klasse abgeleitet. Die Währungsklasse ist hingegen \Alvine\Measure\Economics\Currency
von \Alvine\Measure\DerivedUnit
abgeleitet.
An dieser Stelle sollte man den Artikel Umgang mit physikalischen Werten in PHP lesen. Hier wird grundlegendes zum Umgang mit Werten und Einheiten beschrieben. An dieser Stelle wollen wir uns Geldbeträge anschauen.
Schauen wir uns zuerst einen Geldbetrag an. Zuerst muss ein Währungsobjekt erstellt werden. Dies erfolgt über die Methode
\Alvine\Measure\Economics\Currencies::getCurrency('EUR')
. Danach wird der Betrag definiert. Die Methode \Alvine\Measure\Economics\Money::valueOf($amount, $currency)
kann sowohl mit Integern als auch mit Fließkommazahlen umgehen.
Definieren wir einen Betrag mit dem Wert (int) 1425
so ist die Ausgabe 1425 EUR
.
// Betrag als Integer 1425,00 €
$EUR=\Alvine\Measure\Economics\Currencies::getCurrency('EUR');
$money=\Alvine\Measure\Economics\Money::valueOf(1425, $EUR);
echo (string) $money;
// -> 1425 EUR
Definieren wir jetzt einen Betrag mit dem Wert (float) 14.25
so ist die Ausgabe (14.25 ± 0.00) EUR
. Der Term ± 0.00
gibt hier die Genauigkeit an.
// Betrag als Float 14,25 €
$EUR=\Alvine\Measure\Economics\Currencies::getCurrency('EUR');
$money=\Alvine\Measure\Economics\Money::valueOf(14.25, $EUR);
echo (string) $money;
// -> (14.25 ± 0.00) EUR
Kommen wir jetzt zurück zu unserer Reise. Sie wollen die Reisekosten für einen 400 km Trip innerhalb der USA in Euro berechnen. Der Preis ist in US-Dollar und der Verbrauch des Autos ist in Meilen pro Gallone angegeben. Wie gehen Sie vor?
Unsere Lösung sieht folgendermaßen aus: Zuerst muss man die Währung, den Wechselkurs und die gewünschte Genauigkeit definieren. Im Anschluss wird der Wechselkurs angegeben. Hier wird mit einem Kurs von 1,17 gerechnet.
Die eigentliche Berechnung erfolgt über $entfernung->divide($verbrauch)->times($benzinpreis)->to($EUR);
Durch die Verwendung der Methoden divide, times
und to wird die Umrechnung und Genauigkeit immer richtig angewendet.
Hier das vollständige Programm:
// Währungen definieren
\Alvine\Measure\Formatter\UnitFormatter::getDefaultFormatter()->label($USD, '$');
\Alvine\Measure\Formatter\UnitFormatter::getDefaultFormatter()->label($EUR, '€');
// Genauigkeit
\Alvine\Measure\Formatter\AmountFormatter::getDefaultFormatter()->setPresicion(2);
// Wechselkurs läuft immer über eine Referenzwährung
\Alvine\Measure\Economics\ReferenceCurrency::setCurrentReference($USD);
\Alvine\Measure\Economics\ReferenceCurrency::getCurrentReference()
->setExchangeRate($EUR, 1.17);
// Die eigentliche Berechnung
$verbrauch=\Alvine\Measure\Amount::valueOf(20,
\Alvine\Measure\NonSI::mile()->divide(\Alvine\Measure\NonSI::gallonLiquidUS())); // 20 mi/gal.
$benzinpreis=\Alvine\Measure\Amount::valueOf(1.2,
$EUR->divide(\Alvine\Measure\NonSI::liter())); // 1.2 €/L
$entfernung=\Alvine\Measure\Amount::valueOf(400,
\Alvine\Measure\MetricPrefix::kilo(\Alvine\Measure\SI::meter())); // 400 km
$kosten=$entfernung->divide($verbrauch)->times($benzinpreis)->to($EUR);
$inDollar=$kosten->to($USD);
// Ausgabe
echo "Verbrauch = $verbrauch\n";
echo "Benzinpreis = $benzinpreis\n";
echo "Entfernung = $entfernung\n";
echo "Kosten der Reise = ".$kosten." ";
echo " (".$inDollar.")";
Das Ergebnis des Programms:
Verbrauch = 20 mi/gal
Benzinpreis = (1.20 ± 0.0) €/l
Entfernung = 400 (m)*1000
Kosten der Reise = (56.45 ± 0.00) € ((66.05 ± 0.00) $)
Unsere Reise kostet also $ 66,05. Dies entspricht bei einem Kurs von 1.17 einen Betrag von 56,45 €. Weitere Informationen zu unseren Komponenten und Anwendungen finden Sie im Dokumentationsportal.