Preisrundung: Unterschied zwischen den Versionen
Root (Diskussion | Beiträge) (Die Seite wurde neu angelegt: M.MMggGGGG# cRauschen = 0.000000001; M = Monetäre Stellen g = geforderte Genauigkeit der IEEE Finanzdatentypen G = Bessere Genauigkeit des...) |
Root (Diskussion | Beiträge) 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 | 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 | |||
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 | 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.