Preisrundung: Unterschied zwischen den Versionen

Aus OrgaMon Wiki
Zur Navigation springen Zur Suche springen
(Die Seite wurde neu angelegt: M.MMggGGGG# cRauschen = 0.000000001; M = Monetäre Stellen g = geforderte Genauigkeit der IEEE Finanzdatentypen G = Bessere Genauigkeit des...)
 
Keine Bearbeitungszusammenfassung
 
(3 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
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).<br>
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.<br>
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 ==
<code>
               M.MMggGGGG#
               M.MMggGGGG#
   cRauschen = 0.000000001;
   cRauschen = 0.000000001;
 
   M = Monetäre Stellen
   M = Monetäre Stellen
   g = geforderte Genauigkeit der IEEE Finanzdatentypen
   g = geforderte Genauigkeit der IEEE Finanzdatentypen
   G = Bessere Genauigkeit des OrgaMon
   G = Bessere Genauigkeit des OrgaMon
   # = injiziertes Rauschen
   # = injiziertes Rauschen
 
   Geforderte Genauigkeit laut IEEE, 4 Stellen NACH den Monitären Stellen
   Geforderte Genauigkeit laut IEEE, 4 Stellen NACH den Monetären Stellen
 
   Hintergrund: "Double" stellt zwar eine sehr hohe Rechen-Genauigkeit zur
   Hintergrund: "Double" stellt zwar eine sehr hohe Rechen-Genauigkeit zur
   Verfügung, es kann aber 0,075 NICHT darstellen.
   Verfügung, es kann aber 0,075 NICHT darstellen.
Zeile 16: Zeile 22:
   dennoch auf ein richtiges Endergebnis, Da zum Beispiel 0,0749999*2 wiederum
   dennoch auf ein richtiges Endergebnis, Da zum Beispiel 0,0749999*2 wiederum
   eine gut darstellbare Zahl (0,16) ergibt.
   eine gut darstellbare Zahl (0,16) ergibt.
  ABER: Beim einem direkten Runden der (0,075 * 100.0)
  passiert der Fehler, dass nach 7 als Ergebnis herauskommt, was
  falsch ist!
   
   
  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
   Lösung: Durch ein künstliches Rauschen, das ausserhalb des geforderten
   Genauigkeits-Bereiches liegt, und somit vernachlässigt werden kann,
   Genauigkeits-Bereiches liegt, und somit vernachlässigt werden kann,
Zeile 31: Zeile 40:
   ungerechtfertigte Springen über den Zaun mit der geforderten Ungenauigkeit
   ungerechtfertigte Springen über den Zaun mit der geforderten Ungenauigkeit
   gerechtfertigt werden kann.
   gerechtfertigt werden kann.
 
   Beispiel:
   Beispiel:
 
   1.0 + 0.0000001 = 1.0000001 immer noch 1
   1.0 + 0.0000001 = 1.0000001 immer noch 1
   1.5 + 0.0000001 = 1.5000001 immer noch 2
   1.5 + 0.0000001 = 1.5000001 immer noch 2
   1.49993 + 0.0000001 = 1.4999301 immer noch 1
   1.49993 + 0.0000001 = 1.4999301 immer noch 1
 
   Wir verhelfen praktisch der Zahl 0,4Periode9 die
   Wir verhelfen praktisch der Zahl 0,4Periode9 die
   mathematisch eigentlich nach runden 0 ist über die
   mathematisch eigentlich nach runden 0 ist über die
   Grenze zu 0,5 die nach runden 1 ist!
   Grenze zu 0,5 die nach runden 1 ist!
 
   entstehender Fehler:
   entstehender Fehler:
 
   Wir rechnen ja Zwischenschritte (vor einer Rundung) mit dem mehr
   Wir rechnen ja Zwischenschritte (vor einer Rundung) mit dem mehr
   als ausreichenden double Typ. Hier passiert also kein Fehler,
   als ausreichenden double Typ. Hier passiert also kein Fehler,
   wird jedoch gerundet schleussen wir einen konstanten Offset ein, der
   wird jedoch gerundet schleussen wir einen konstanten Offset ein, der
   nur einem 100stel der geforderten Genauigkeit entspricht. Also
   nur einem 100stel der geforderten Genauigkeit entspricht. Also
   akzeptabel und inerhalb eines gegebenen Toleranzbandes.
   akzeptabel und innerhalb eines gegebenen Toleranzbandes.
 
*)
</code>

Aktuelle Version vom 8. November 2017, 10:30 Uhr

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.