Thread Runden *war Subtrahieren in Perl ... (55 answers)
Opened by Muffi at 2013-09-25 10:41

pq
 2013-09-26 01:01
#170648 #170648
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
es gibt ja im grunde 2 probleme. einmal das runden im dezimalsystem:
kunde bestellt produkt X, was 9,95€ kostet und bekommt 50% rabatt.
er bezahlt dann nicht 4,975€, sondern 4,98€. (oder wie auch immer man sich da als verkäufer entscheidet).
bestellt er das produkt gleich 4 mal, wären das 39,80€ oder mit rabatt 19,90€.
man kann sich hier entscheiden, ob man jedes einzelne produkt mit rabatt rundet und dann aufsummiert (4,98€ mal 4 = 19,92€) oder den rabatt auf die summe gibt (9,95€ / 2 * 4 = 19,90€).
das ist alles im dezimalsystem und wenn man weiss, wann man wie runden möchte/muss, alles machbar.

in cent oder centicent zu rechnen, kann einem da helfen, aber es gibt da auch fälle, bei denen fliesskommazahlen herauskommen können. auch da kann man dann aber regeln für die rundung anwenden.

das zweite problem:

wenn man jetzt aber im binärsystem rechnet (die zahlen aber immer als dezimal sieht), vergisst man, dass sich eben manche fliesskommazahlen nicht exakt binär ausdrücken lassen. die "fehler" zeigen sich dann erst, wenn man mehrere berechnungen durchführt und dann seine rundungsfunktion darauf loslässt.
wenn man kann, sollte man also möglichst in cent oder centicent rechnen. hat man dennoch stellen hinter dem komma, muss man immer im hinterkopf behalten, dass die zahl, die man in die variable einspeist, nicht so abgespeichert wird, wie man sie im dezimalsystem vor augen hat. als lösung könnte man nach jeder berechnung die zahl auf die gewünschte anzahl kommastellen runden, damit der fehler klein genug bleibt, um am ende keine rolle zu spielen.
also: führt man eine berechung mit fliesskommazahlen durch, "entfernt" man den fehler beispielsweise mit sprintf direkt danach.

damit würde sich die frage stellen: woher kommt die beispielzahl 0.05499999999999999334? ergebnis einer kaufmännischen berechnung oder entstanden durch mehrere fliesskommazahlenberechnungen ohne korrektur?
wenn es das ergebnis einer kaufmännischen berechnung ist und das, was perl dir dezimal anzeigt, dann ist es eben nicht 0.05499999999999999334, das ist nur die näherung der zahl im dezimalsystem. das ist dann im zweifel eher 0.055 als 0.054. wenn es eine eingabe als string ist, dann kannst du es mit Math::BigFloat versuchen, da kommt dann auch 0.05 beim runden heraus.

der einwand von muffi ist schon berechtigt, dass es wichtig ist, woher die zahl kommt.
und auch, dass es eben keine eine funktion gibt, die dir alle fälle löst.

also: fehler von berechungen ggfs. mit sprintf klein halten nach jeder berechnung. wenn 0.05499999999999999334 bei einer berechnung herauskommt, ist es nicht 0.05499999999999999334, sondern nur die beste näherung, die perl dir anzeigt. daher ist 0.06 nicht so falsch.
wenn 0.05499999999999999334 exakt so dezimal vorliegt, arbeite mit Math::BigFloat.
Last edited: 2013-09-26 01:08:27 +0200 (CEST)
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem

View full thread Runden *war Subtrahieren in Perl ...