Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Gleitpunktarithmetik - Diskrepanzen (https://www.delphipraxis.net/59179-gleitpunktarithmetik-diskrepanzen.html)

alzaimar 19. Dez 2005 14:47

Re: Gleitpunktarithmetik - Diskrepanzen
 
Probiers aus.

dizzy 19. Dez 2005 14:51

Re: Gleitpunktarithmetik - Diskrepanzen
 
Lösung des Problems (markieren zum Lesen):


Die 0 ist als Float (Single, Double, Extended, ...) garnicht darstellbar ;). Für die 0 wird in der FPU ein separates Flag pro Register mitgeführt, und es ist so gut wie nie der Fall, dass eine Berechnung exakt 0 ergibt (eben wegen der üblichen Ungenauigkeit bei Floats). Deswegen gilt auch: Prüfe ein Float nie dirket auf Gleichheit mit 0! (bzw. überhaupt nicht direkt auf Gleichheit)

"Hier liegt Alles im grünen Bereich, sämtliche Zwischenergebnisse, Startwerte etc.
Oder vielleicht doch nicht?"

All diese Werte liegen folglich im Bereich, jedoch nicht der Wert mit dem verglichen wird - der 0! :zwinker:


-------------------

alzaimar 19. Dez 2005 16:39

Re: Gleitpunktarithmetik - Diskrepanzen
 
Einen hab ich noch: Kein Vergleich, keine 0, nur simples Addieren. Alle Zwischenergebnisse innerhalb des Wertebereiches.
Delphi-Quellcode:
Var
  x : Double;
  i : Integer;
begin
  x:=-1;
  For i:=1 to 10000 do x := x + 0.1;
  For i:=1 to 10000 do x := x - 0.1;
  memo.lines.add (FloatToStr(x));
end;
Was kommt raus (x + 10000*0.1 - 10000*0.1 = ?)
Bei Extended muss man ca. 500x öfter rechnen. Kann es sein, das auch die 0.1 nicht 100%ig akkurat dargestellt werden kann?

dizzy 19. Dez 2005 16:54

Re: Gleitpunktarithmetik - Diskrepanzen
 
Das Ergebnis ist sicher nicht x 8)

Ich habe hier schon mal 0.2 binär dargestellt, und es wurde periodisch. Unter der Annahme dass eine halbierte periodische Zahl weiterhin periodisch ist, würde dies auch auf 0.1d zutreffen. Dadurch passt die Mantisse nicht in die dafür vorhandenen Bits (müssten ja unendlich viele sein :stupid:), und schon allein das hinterlegen des Wertes "0.1" in der FPU erzeugt eine Ungenauigkeit. Diese summiert sich auf, und wird aber nicht in gleicher Weise wieder abgezogen in der 2. Schleife! Ungenauigkeiten bei Floats haben so die Eigenschaft mit jeder weiteren Rechnung immer schlimmer zu werden als besser :D
Folglich wird das Ergebnis nachher x+-e heissen, wobei e eine beliebige kleine (nicht beliebig kleine! ;)) reelle Zahl ist, wenn nur ausreichend Zwischenschritte ausgeführt werden.

Khabarakh 19. Dez 2005 17:49

Re: Gleitpunktarithmetik - Diskrepanzen
 
Ich finde das Thema rationale Zahlen in binärer Schreibweise ziemlich interessant, vor allem da es nicht im Schulstoff vorkommt (ganze binäre Zahlen schon in der 5.) und ich ohne Real/Double gar nicht wüsste, dass es so etwas gibt :stupid: . Solche Zahlenkolonnen wie "01110100010" kommen einem ja bekannt vor, aber "11,010" ist ersteinmal doch etwas ungewohnt.
Folgendes lässt sich ja problemlos kompilieren:
Delphi-Quellcode:
begin
  x:=-0.5;
  while x<0.2 do begin
    if x=0 then
      memo.lines.add('[:-)')
    else
      memo.Lines.Add(FloatToStr(x));
    x := x+0.125;
    End;
end;
Besonders interessant finde ich die Lösung im .NET-Framework für genaue Fließkommazahlen: m * 10 ^ -e

alzaimar 19. Dez 2005 19:49

Re: Gleitpunktarithmetik - Diskrepanzen
 
dizzy: Du weisst mehr als ich. Ich wusste nur, das 0.1 nicht exakt dargestellt ist (periodisch)... Ich hab vor 25 Jahren diese Floating-Point Macken erlebt, als unser damalige Rechner (ein HP 9845) durch einen HP300 (mit Motorola 68k) ausgetauscht wurde und die Rechnungen statt mit BCD in der wesentlich schnelleren Floating-Point Arithmetik durchgeführt wurden.

Es ist auf jeden Fall ein sehr wichtiger Aspekt, wenn man weiss, das man zwar schnell rechnen kann, aber das Ergebnis mit einer gehörigen Portion Argwohn betrachten sollte. Bei komplexen Berechnungen, insbesondere iterativen Näherungen, kann sich der anfänglich marginale Fehler sehr schnell in den 1E-5er Bereich potenzieren, was dann gar nicht mehr lustig ist. Man muss dann z.B. die Vorgaben erst normalisieren, also in die Nähe von 1-100 bringen, um den Fehler wieder zu minimieren. Im Extremfall klappt das aber auch nicht.

negaH 20. Dez 2005 05:40

Re: Gleitpunktarithmetik - Diskrepanzen
 
Extended geht von 3.6e10^-4951 bis 1.1e10^4932 und hat eine Manitisse von 64 Bit. Die Mantisse kann also nur 2^64 Zahlen korrekt darstellen * Bereich des Exponenten = 2^16 = 2^80.

Aus einem gesammten Zahlenbereich von 2^1024 können nur 2^80 Zahlen exakt in einem Extended gespeichert werden, das sind 0,00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00672 48730 95247 25964 69121 5039 Prozent
== 1/2^944.

Man kann also mit annähernd 100 Prozent davon ausgehen das eine Fließkommaberechnung immer "falsch" rechnet.

Extendend hat 10 Bytes = 10*8 = Speicherbereich 2^80. Der Exponent fasst 16 Bits = 2^16 und Mantisse 64 Bits = 2^64. Maximal speicherbar also 2^64 * 2^16 = 2^80, maximaler Wertebereich der Zahlen 2^(64 * 16) = 2^1024.
2^1024 / 2^80 = 2^944 Zahlen aus dem gesammten Wertebereich des Extended können nicht exakt gespeichert werden.Dabei ist es irrelevant ob man nur mit kleinen Zahlen annähernd 0.0 rechnet, der "Fehler" ist gleichverteilt.

Gruß Hagen

alzaimar 20. Dez 2005 07:35

Re: Gleitpunktarithmetik - Diskrepanzen
 
@negaH: So logisch einfach hab ich das noch nie gesehen. :thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:31 Uhr.
Seite 2 von 2     12   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz