Seite 1 von 1

Rundungsfehler

Verfasst: Di, 27. Mär 2018 13:13
von Jan
Ich hatte gerade eine interessante Diskussion mit einem Kunden. Und brauch da mal Eure Sachkenntnis.

Wir leben ja ständig mit dem Problem der CPU-Rundungsfehler.Die zwar erst irgendwo in der 4. oder 6. Stelle auftreten, aber doch irgendwo relevant werden können.

Wie verhält sich das aber exakt? Kann ein 1,87 € nur irgendwo zwischen 1,87 € und 1,870001 € liegen? Oder auch 1,8699999 € sein? Soll sagen: Rundungsfehler nur nach oben? Oder auch runter?

Jan

Re: Rundungsfehler

Verfasst: Di, 27. Mär 2018 13:15
von brandelh
in beide Richtungen, wobei ich denke, dass es wahrscheinlicher nach unten geht

Re: Rundungsfehler

Verfasst: Di, 27. Mär 2018 13:22
von brandelh
Ich habe einmal ein Programm geschrieben, das für viele Monate Leistungen nachberechnet hat, da war auch Verzinsung nötig.
Beim reinen addieren ist das meist kein Problem, aber je Monat wurden die 4 % Zinsen berechnet und gedruckt.
Die Summe im berechneten Summen-Feld und die manuelle Summe über die Zeilen, konnten einige Euro ausmachen.

Daher habe ich dann in jeder Zeile den Zinsbetrag auch intern gerundet, bevor ich den addiert habe, danach war es gut.

Aber um auch bei großen Beträgen wirklich sicher zu sein, müsste man einen speziellen Datentyp haben.
Unser Wirtschafts-Basic in der Schule konnte mit richtigen Dezimalzahlen rechnen (die haben das irgendwie nachgebildet) ...
Andere Systeme nutzen 64 Bit Ganzzahlen und rechnen in Bruchteilen von Cent ...

25,55 => intern dann als 64 bit Integer => 255500 Cent/10000

Re: Rundungsfehler

Verfasst: Di, 27. Mär 2018 14:14
von DelUser01
Hallo Jan

habe auch seit Jahren manchmal noch so ein Rundungsproblem und noch nicht herausgefunden woran es liegt.

Z.B.
Es wird berechnet (zusammengezählt) was heute bezahlt (überwiesen) werden muss.
Der User bekommt eine Zahl in einem SLE angezeigt - z.B. 25.000,00 Euro
und wird gefragt wieviel er bezahlen will. Er bestätigt den Betrag 25.000,00 mit Return.
Dann kommt es manchmal vor, dass das eine Rechnung weglässt weil 1 Cent zu wenig bestätigt wurde.
Also war die angezeigte Zahl nicht 25.000,00 sondern z.B. 25.000,000001 oder so.
Der Kunde hat sich dran gewöhnt und gibt meist automatisch schon 1 Cent mehr ein.
Warum auch immer... ist doch doof.

In meinem Errorlog sind solche Zahlen häufiger zu sehen
wenn ich eine Zahl ausgebe mit
? "Code: " , nCode
Da steht dann im Log z.B:
Code: 15,9999999... usw. , nZahl ist aber 16.
Gebe ich die Zahl aus mit ? Var2Char( nCode ) wird wieder 16 angezeigt.
Für die Wandlung von nCode in einen String habe ich auch eine Funktion welche bei derselben Zahl auch keine Rundungsprobleme macht. Die Funktion schaut wie viele Kommastellen der Wert hat und schneidet diese dann ab. Wenn die Zahl im Speicher 16,000000000 hat steht im String "16" und nicht die 15,999999

Das ist immer wieder seltsam...

Re: Rundungsfehler

Verfasst: Do, 29. Mär 2018 17:21
von DennisK
Das alte Problem mit den Gleitkommazahlen. Irgendwann wird halt abgeschnitten.

10/3 = 3,33333333333333333333
3,33333333333333333333*3 = 9,99999999999999999999

Das ist halt Annähern und kein genaues Rechnen.

Re: Rundungsfehler

Verfasst: Di, 03. Apr 2018 11:35
von Statler
Hallo zusammen,

Binaer kann nicht immer verlustfrei nach Dezimal gewandelt werden und umgekehrt. Da liegt das grundsaetzliche Problem

nZahl:= ROUND (nZahl + 0.0001, 2)

So bearbeite ich meien Euro Werte, wenn es Probleme geben koennte

Gruss

Achim

Re: Rundungsfehler

Verfasst: Di, 03. Apr 2018 11:40
von Tom
Binaer kann nicht immer verlustfrei nach Dezimal gewandelt werden und umgekehrt.
Bitte was? :shock: Binäre und dezimale Zahlendarstellungen machen exakt das gleiche, nur zu einer anderen Basis. Selbstverständlich geht das immer und immer in beide Richtungen völlig verlustfrei.

Re: Test Mapi

Verfasst: Di, 03. Apr 2018 13:35
von Statler
Hallo,

ich rede von gebrochenen Zahlen!

ich kann mich noch schwach an eine Vorlesung ueber verschiedene Formen der Zahlendarstellungen erinnern, da wurde aud das Problem bei Real-Zahlen explizit hingewiesen. Daher darf man eine Real-Zahl auch nie auf 0 Pruefen, sondern auf < 0,....1.

https://www.sps-lehrgang.de/umrechnung- ... malzahlen/

Ich bin bereits mehrfach auf das Problem gestossen, das bei der Addition/Subtraktion von Euro-Werten aus der Datenbank, also definitiv nur 2 Stellen, hin und wieder irgendwas auf der x-ten Stelle erscheint. Sowas kann eigentlich nicht sein ...

Wenn man dann versucht, auf 0 zu pruefen (Konto ist ausgeglichen) gibt es hin und wieder, jedoch streng reproduzierbar, Probleme.

Gruss

Re: Rundungsfehler

Verfasst: Di, 03. Apr 2018 14:02
von brandelh
Ähem ... TOM, nicht mit den verwendeten 8 Bit Fließkomma Zahlen, wenn die Genauigkeit höher geht, gibt es da immer Verluste.

Re: Rundungsfehler

Verfasst: Di, 03. Apr 2018 14:30
von brandelh
Aus dem Grunde vergleiche ich gerne mit Str(nWert1,18) == Str(nWert2,18)
Wenn man es sicher machen will, muss man noch die ********* beim Zahlenüberlauf abfangen ;-)

Re: Rundungsfehler

Verfasst: Di, 03. Apr 2018 15:13
von Tom
Ihr redet von reellen und natürlichen Zahlen. Und selbst bei denen gilt: Eine Zahl, die sich dezimal (zur Basis 10) repräsentieren lässt, lässt sich verlustfrei auch binär (zur Basis 2) repräsentieren. Zumindest theoretisch. Denn 1/3 zum Beispiel lässt sich als einzelne Zahl überhaupt nicht repräsentieren, jedenfalls nicht vollständig.

Re: Rundungsfehler

Verfasst: Di, 03. Apr 2018 15:35
von DelUser01
Das ist doch genau der Effekt von dem ich weiter oben schon geschrieben habe.

Re: Rundungsfehler

Verfasst: Di, 03. Apr 2018 20:41
von Statler
Hallo Tom.

n:= 0.876 / 3 * 3
debugout (STR (n, 24, 16))

da sollte eigenlich 0.876 rauskommen, aber 0.8759999999... erscheint.

Wie gesagt,
https://www.sps-lehrgang.de/umrechnung- ... malzahlen/
das Beispiel ganz unten macht die Sache klar.

Gruss

Re: Rundungsfehler

Verfasst: Mi, 11. Apr 2018 12:17
von UliTs
Tom hat geschrieben: Di, 03. Apr 2018 15:13 Ihr redet von reellen und natürlichen Zahlen. Und selbst bei denen gilt: Eine Zahl, die sich dezimal (zur Basis 10) repräsentieren lässt, lässt sich verlustfrei auch binär (zur Basis 2) repräsentieren. Zumindest theoretisch. Denn 1/3 zum Beispiel lässt sich als einzelne Zahl überhaupt nicht repräsentieren, jedenfalls nicht vollständig.
Z.B. 0,1 oder 0,9 lassen sich nicht im Binärsystem darstellen. Deshalb ist bei Binärsystem oft 0,1 + 0,9 <> 1,0 :-)

Re: Rundungsfehler

Verfasst: Mi, 11. Apr 2018 12:57
von Tom
Ui, Uli.

Den Rechenvorgang, bei dem 0,1 + 0,9 nicht 1,0 ergibt, musst Du mir mal zeigen. Das schaffst Du nicht einmal auf einem 4-Bit-Robotron-Rechner von 1979.

Binär repräsentierte Gleitkommazahlen nach IEEE 754 (Bits für Vorzeichen, Exponenten und Mantissen) sind sehr wohl äußerst präzise und stimmen meistens mit ihrer Dezimalrepräsentation für viele Nachkommastellen überein. Es gibt möglicherweise Artefakte bei bestimmten Bruchzahlen. Aber wenn es bei solchen Berechnungen wie der von Dir erwähnten tatsächlich Probleme gäbe, wäre es besser, die Rechner komplett wegzuschmeißen.

Re: Rundungsfehler

Verfasst: Mi, 11. Apr 2018 13:28
von brandelh
bevor Ihr euch kloppt ...

:arrow: https://de.wikipedia.org/wiki/IEEE_754
Hilfe zu 2.00 hat geschrieben:Numeric values are handled within Xbase++ in the IEEE 64 bit format for floating point numbers.
This provides a range for calculations of 10 to the power of -307 to 10 to a power of +308.
The binary representation of a floating point number yields a 16 decimal digit precision.

The display of numeric values on the screen is predictable only up to 16 places before the decimal and 15 places after the decimal.
Numeric values are displayed with a maximum of 31 digits.
If there are more pre or post decimal numerals, asterisks * or nulls 0 are shown in the display of the number.
Richtig ist, dass mit diesen Werten schon sehr große Zahlen benötigt werden um eine Differenz zu erzeugen und dass immer wenn Perioden im Spiel sind,
weder mit dem einen noch mit dem anderen eine Exakte Angabe möglich ist. Daher kürzt man ja solche Berechnungen auch gerne.

Man muss immer Aufpassen, ob bei seinen Zahlenbereichen Rundungsfehler eine Rolle spielen könnten, Vergleiche auf = würde ich daher immer mit STR(nWert) oder Round() durchführen,
wobei die "*" beim Überlauf berücksichtigt werden müssen.

Ich denke, dass vieles von dem was wir an Fehlern erwartet hätten auf DOS Clipper zurück geht,
haben wir dort schon so große Zahlen gehabt oder waren es da nur 8 Stellen nach dem Komma oder 15 insgesamt ... ich weiß es nicht mehr.
Ich meine aber Clipper hatte mit 32 Bit Single Floating Point deutlich weniger Genauigkeit.

Zum Test habe ich mal diese Formeln eingegeben und Berechnen lassen:

Code: Alles auswählen

Berechnungen:
0.1 + 0.9               =>           1.0
0.1 + 0.9 = 1.0         =>           J
1   - 0.1 - 0.9         =>           0.0
1   - 0.1 - 0.9 = 0     =>           J
1.0 - 0.1 - 0.9 = 0     =>           J

Ende

Re: Rundungsfehler

Verfasst: Mi, 11. Apr 2018 14:10
von UliTs
Tom hat geschrieben: Mi, 11. Apr 2018 12:57 Ui, Uli.

Den Rechenvorgang, bei dem 0,1 + 0,9 nicht 1,0 ergibt, musst Du mir mal zeigen. Das schaffst Du nicht einmal auf einem 4-Bit-Robotron-Rechner von 1979.

Binär repräsentierte Gleitkommazahlen nach IEEE 754 (Bits für Vorzeichen, Exponenten und Mantissen) sind sehr wohl äußerst präzise und stimmen meistens mit ihrer Dezimalrepräsentation für viele Nachkommastellen überein. Es gibt möglicherweise Artefakte bei bestimmten Bruchzahlen. Aber wenn es bei solchen Berechnungen wie der von Dir erwähnten tatsächlich Probleme gäbe, wäre es besser, die Rechner komplett wegzuschmeißen.
Hallo Tom,

dann versuche doch einmal 0,1 im Binärsystem bei endlicher Stellenanzahl darzustellen -> geht nicht ;-) .