Vor kurzem hatte ich mal wieder eine Diskussion über Rundungsfehlern bei Fließkommazahlen (double, float etc.). Klar, ein bekanntes Problem, von dem man zumindest in der Uni schon einmal gehört haben sollte. Aber wie schrieb schon Tom DeMarco in „Warum ist Software so teuer?“
Haben Sie jemals einen dummen Fehler begangen? – Wilkommen in der realen Welt.
Haben Sie diesen Fehler hundertmal hintereinderander gemacht? – Willkommen in der Software-Entwicklung.
Witzigerweise schaute ich am darauf folgenden Wochenende einen Vortrag von Dan Bergh Johnsson über Value Objects (The Power of Value – Power Use of Value Objects in Domain Driven Design), als Johnsson mich mit den Augen durch mein iPad hindurch fixierte und in Minute 23 in etwa folgendes sagte:
I hope no one here use double for monetary amounts or financial calculations. […] You can`t represent a houndredth exactly in a binary representation.
Also merken wir uns, jetzt und für alle Zeit: Wenn wir mit Geld rechnen wollen, benutzen wir (zumindest in PHP) Ganzzahlen (integer) und keine Fließkommazahlen (float). Am Beispiel Euro: In unseren Variablen halten wir nicht die Anzahl an Euro, sondern die Anzahl an Euro-Cent, die sich wiederum wunderbar als Ganzzahl repräsentieren lassen.
Am Besten funktioniert das natürlich gekapselt in einem Value Object, welches eine durch einen String realisierte Dezimalzahl zurück geben kann, die je nach Region einen Punkt oder ein Komma als Dezimal-Trenner verwendet.
Vertiefend kann ich zu diesem Thema die folgenden Blog-Beiträge empfehlen:
- A story about an angry carrot and a floating point fairy
- What every scientist should know about floating-point arithmetische
Und noch etwas: Falls ihr euch jetzt fragt, warum die PHP-Funktion money_format() als Parameter float und nicht integer übergeben bekommt … nunja … vielleicht arbeiten am PHP-Kern eben auch nur Menschen …