Preisrundung

Aus OrgaMon Wiki
Version vom 8. November 2017, 10:30 Uhr von Root (Diskussion | Beiträge)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Anwendungen der Finanzbuchhaltung verwenden in der Regel besondere Datentypen um Rechenungenauigkeiten der Standard-Fliesskomma-Zahlen aus dem Weg zugehen. Das Problem entsteht insbesondere beim Runden. So kann es im Fliesskomma-Bereich vorkommen, dass 0,5 oder 0,75 nicht korrekt dargestellt werden kann. Ein Runden kann nun dazu führen dass fälschlicherweise 0,5 auf 0 abgerundet wird (d.h. wenn die interne Darstellung der Zahl eher 0,49999999999999999999 entspricht als 0,5).
Bei dieser Diskussion geht es nicht um Rechenfehler in der 5. Stelle nach dem Komma, die sich 1000 fach angewendet dann zu einigen Euros summieren. Nein, vielmehr geht es um massive Anweichungen (also z.B. ein ganzer Cent) innerhalb eines Kundenbeleges.
Es wurde beobachtet dass je nach Rechenweg z.B. a=(12 * 0,5) b=(8 * 0,75) Round(a)<>Round(b) ist. Also ganz offensichtliche und Massive abweichungen durch "Rundungsfehler", Ursache Wirkung und Lösung wird in der Folge beschrieben.

Lösung der Rundungsproblematik

              M.MMggGGGG#
  cRauschen = 0.000000001;

  M = Monetäre Stellen
  g = geforderte Genauigkeit der IEEE Finanzdatentypen
  G = Bessere Genauigkeit des OrgaMon
  # = injiziertes Rauschen
 
 Geforderte Genauigkeit laut IEEE, 4 Stellen NACH den Monetären Stellen
 
 Hintergrund: "Double" stellt zwar eine sehr hohe Rechen-Genauigkeit zur
 Verfügung, es kann aber 0,075 NICHT darstellen.
 Es kann nur 0,07499999... darstellen, was bei der direkten Betrachtung der
 Zahl sofort auffällt. Würde man jedoch mit dieser Zahl weiterrechen käme man
 dennoch auf ein richtiges Endergebnis, Da zum Beispiel 0,0749999*2 wiederum
 eine gut darstellbare Zahl (0,16) ergibt.

 ABER: Beim einem direkten Runden 

 Round(0,075 * 100.0) * 100.0 = 0,07

 passiert der Fehler, dass nach 0,07 als Ergebnis herauskommt, was falsch ist. Man würde 0,08 erwarten!
 
 Lösung: Durch ein künstliches Rauschen, das ausserhalb des geforderten
 Genauigkeits-Bereiches liegt, und somit vernachlässigt werden kann,
 wird sichergestellt, dass die Rundung gesichert so gelingt wie es
 erwartet wird:
 Im Prinzip verhilft man den zahlen, die hoffnungslos in der Perioden
 darstellung gefangen sind durch einen leichten Schups über den Zaun.
 Bei Zahlen die eigentlich den Schups nicht benötigt hätten und
 gerne nicht gesprungen wären machen wir einen Fehler, OK, aber
 dieser liegt ausserhalb der geforderten Genauigkeit, so dass dass
 ungerechtfertigte Springen über den Zaun mit der geforderten Ungenauigkeit
 gerechtfertigt werden kann.
 
 Beispiel:
 
 1.0 + 0.0000001 = 1.0000001 immer noch 1
 1.5 + 0.0000001 = 1.5000001 immer noch 2
 1.49993 + 0.0000001 = 1.4999301 immer noch 1
 
 Wir verhelfen praktisch der Zahl 0,4Periode9 die
 mathematisch eigentlich nach runden 0 ist über die
 Grenze zu 0,5 die nach runden 1 ist!
 
 entstehender Fehler:
 
 Wir rechnen ja Zwischenschritte (vor einer Rundung) mit dem mehr
 als ausreichenden double Typ. Hier passiert also kein Fehler,
 wird jedoch gerundet schleussen wir einen konstanten Offset ein, der
 nur einem 100stel der geforderten Genauigkeit entspricht. Also
 akzeptabel und innerhalb eines gegebenen Toleranzbandes.