Problem bei addition von Kommazahlen

03/26/2012 17:32 Lawliet#1
Hallo,
Ich beschäftige mich gerade mit GDIPlus und diesbezüglich mit Parabeln usw.
Dabei habe ich eine Schleife nach diesem Schema:
Code:
$x = -100
do
	$x+=0.01
	ConsoleWrite($x & @CRLF)
Until $x >= 100
Warum entstehen nun Zahlen mit mehr als 2 Nachkommastellen?

03/26/2012 17:43 xNopex#2
Liegt wohl an der internen Speicherung. Da nur begrenzt Speicherplatz zur Verfügung steht, muss man Abstriche bei der Genauigkeit machen. Bedenke nur: Zwischen 0 und 1 liegen unendlich viele Kommzahlen! Man trennt den Speicherbereich ungefähr folgendermaßen auf:

vorzeichenbit | exponent | mantisse

Jetzt finden intern noch Normierungsverfahren statt, damit mehr Zahlen abgespeichert werden können und zum leichteren Rechnen für das Rechenwerk. Das alles verändert die Zahl natürlich. Sprich: Du erhälst mehr als zwei Nachkommastellen wegen der internen Speicherung der Zahl.
Lösung: Runde nach zwei Stellen.
03/26/2012 17:46 Freddy​#3
^
Aber zum Runden der Zahl kannst du Round() benutzen
03/26/2012 17:48 jacky919#4
Quote:
Originally Posted by xNopex View Post
Liegt wohl an der internen Speicherung. Da nur begrenzt Speicherplatz zur Verfügung steht, muss man Abstriche bei der Genauigkeit machen. Bedenke nur: Zwischen 0 und 1 liegen unendlich viele Kommzahlen! Man trennt den Speicherbereich ungefähr folgendermaßen auf:

vorzeichenbit | exponent | mantisse

Jetzt finden intern noch Normierungsverfahren statt, damit mehr Zahlen abgespeichert werden können und zum leichteren Rechnen für das Rechenwerk. Das alles verändert die Zahl natürlich. Sprich: Du erhälst mehr als zwei Nachkommastellen wegen der internen Speicherung der Zahl.
Lösung: Runde nach zwei Stellen.
Bei einer nativen Sprache wie C++ mag das stimmen. Aber da AutoIt dynamische Typen verwendet könnte es sein, dass alle Zahlen als Strings abgespeichert werden und je nach Verwendung intern in Zahlen umgewandelt werden.
03/26/2012 17:55 xNopex#5
Quote:
Bei einer nativen Sprache wie C++ mag das stimmen. Aber da AutoIt dynamische Typen verwendet könnte es sein, dass alle Zahlen als Strings abgespeichert werden und je nach Verwendung intern in Zahlen umgewandelt werden.
Trotzdem müssen die Dezimalzahlen abgespeichert werden. Und das Rechenwerk schließlich mit den Zahlen rechnen. Sie werden eben erst zur Laufzeit dann umgewandelt.
03/26/2012 19:58 lolkop#6
um dem entgegen zu wirken kannst du dir über stringfunktionen aber durchaus eine eigene funktion schreiben, welche nachkommastellen und vorkommastellen seperat als integer handelt, und somit der ungenauigkeit der floatingpoint operation entgegen wirken.
03/26/2012 20:07 xNopex#7
Quote:
um dem entgegen zu wirken kannst du dir über stringfunktionen aber durchaus eine eigene funktion schreiben, welche nachkommastellen und vorkommastellen seperat als integer handelt, und somit der ungenauigkeit der floatingpoint operation entgegen wirken.
Oder einfach die Zahlen jeweils mit 100 Multiplizieren und am Schluss wieder durch 100 teilen.
03/26/2012 20:16 lolkop#8
Quote:
Originally Posted by xNopex View Post
Oder einfach die Zahlen jeweils mit 100 Multiplizieren und am Schluss wieder durch 100 teilen.
in diesem falle mag das funktionieren, bei unbekannter bzw varrierender anzahl der nachkommastellen hingegen kann man so nicht an das problem gehen, zumal bei hoher anzahl von nachkommastellen durch die division ja auch wieder rundungsfehler entstehen könnten.
03/26/2012 20:30 xNopex#9
Quote:
bei unbekannter bzw varrierender anzahl der nachkommastellen hingegen kann man so nicht an das problem gehen
Eigentlich ist das gängige Praxis. Natürlich geht das nicht immer, aber in sehr sehr vielen Fällen. Es gibt dabei auch Möglichkeiten so bei unbekannter oder variierender Anzahl an Nachkommastellen zu verfahren.
Man wird dabei auch immer genauere Ergebnisse erzielen als bei der gleichen Rechnung in Gleitkommarithmetik. Je mehr Rechenschritte notwedig sind, desto genauere Ergebnisse wird dieses Verfahren liefern. Rundungsfehler treten dann wenn überhaupt im letzten Schritt bei der Rücktransformation auf.
03/26/2012 21:27 Lawliet#10
Naja, in meinem Falle hat das Runden auf 2-4 Kommastellen vollkommen gereicht ;)
Danke