Autor |
Beitrag |
monty.ms
      
Beiträge: 47
|
Verfasst: So 15.05.05 15:44
hallo
ich hab mal eine kleine frage zu diesem Code:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| var x1,x2:real; begin x1:=0.2; x2:=x1-0.2; label1.Caption:=floattostr(x2); end; |
.. der ist ja eigentlich richtig, doch warum kommt als Ergebnis nicht 0 raus, sondern 1,1099519E-17 ??
ist das ein fehler von delphi?
ps: sry wenn es hier schonmal war und nochmals sry wenn das der falsche Bereich ist =)
Moderiert von raziel: Code- durch Delphi-Tags ersetzt.
Moderiert von raziel: Topic aus Sonstiges verschoben am So 15.05.2005 um 16:00
Zuletzt bearbeitet von monty.ms am So 15.05.05 16:10, insgesamt 1-mal bearbeitet
|
|
Fabian W.
      
Beiträge: 1766
Win 7
D7 PE
|
Verfasst: So 15.05.05 16:01
Das Problem hatte ich auch mal, aber nur in kleinen Bereichen 0.1-0.1, aber da kam auch immer schrott raus.
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 15.05.05 16:04
Benütze statt real extended.
Das ist übrigens kein Fehler von Delphi; das wird über die Hardware gerechnet. Die Zahl die du erhältst ist unterhalb der Maschinengenauigkeit. Ich nehm mal die Ungenauigkeit kommt vom Runden oder sowas.
Die Zahl 0.2 lautet im Binärsystem 0.001100110011... (periodisch).
Je nach dem bei welchem Schritt der Berechnung genau gerundet wird, kommt's halt anders raus.
Fabian W.: Was denn für "Schrott"? Die Abweichung ist doch minim.
|
|
Fabian W.
      
Beiträge: 1766
Win 7
D7 PE
|
Verfasst: So 15.05.05 16:20
Und was ist bei extended jetzt anders?
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 15.05.05 16:29
Extended ist noch ein bisschen genauer als Double-Precision (real).
|
|
Fabian W.
      
Beiträge: 1766
Win 7
D7 PE
|
Verfasst: So 15.05.05 16:32
rechnet aber auch per Maschiene? Dann kann ich gleich runden wenn real schon ist...
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 15.05.05 16:41
Fabian W. hat folgendes geschrieben: | rechnet aber auch per Maschiene? Dann kann ich gleich runden wenn real schon ist... |
Ja, auch Extended geht über die FPU. Der Unterschied zu Double ist, dass bei Extended alle Zahlen vor der Berechnung in den FPU Stack geladen werden müssen, bevor eine Berechnung stattfinden kann. So ist die ganze Sache symmetrisch und es wird immer beim gleichen Schritt gerundet. Bei Double ist dies nicht unbedingt notwendig und somit geschieht dort die Rundung nicht immer symmetrisch.
Könnte mich aber täuschen, bin kein FPU Experte.
Zur zweiten Bemerkung: Ich sagte, die Abweichung zum korrekten Resultat ist minim. Wenn du die Zahl richtig formatiert darstellst (siehe z.B. floattostrf) dann sieht man den kleinen Fehler auch nicht. Aber gegen die Tatsache, dass der Rechner nicht exakt rechnen kann, kannst du nichts tun.
|
|
Fabian W.
      
Beiträge: 1766
Win 7
D7 PE
|
Verfasst: So 15.05.05 16:57
Wie macht das dann der taschenrechner?
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 15.05.05 17:02
Dein Taschenrechner rechnet entweder Dezimal oder rundet beim Anzeigen der Zahlen die letzten 3 Stellen weg (oder keines der beiden).
So, das waren jetzt bald genug deiner Fast-Off-Topic Fragen, findeste nicht auch? Im Prinzip geht es hier ja um monty.ms. Wenn du dich so sehr für die Sache interessierst, schau mal im Google unter "Floating Point Arithmetic IEEE".
|
|
Fabian W.
      
Beiträge: 1766
Win 7
D7 PE
|
Verfasst: So 15.05.05 17:10
Also, gut. Die Frage war ja geklärt.
|
|
juppinger
      
Beiträge: 50
|
Verfasst: Di 03.05.11 12:15
Hallo zusammen,
prima dass ich den gleichen Fehler in meinem Programm entdeckt habe bzw. darauf hingewiesen wurde und in diesem Forum sofort etwas gefunden habe
Aber jetzt kommt's:
Ich habe eine Version des Programms erstellt, in der ich von REAL auf EXTENDET umgestellt habe. - Mehr habe ich wirklich nicht gemacht, ausser den Datentyp geändert.
Tests auf diversen (neueren) PCs mit untersch. Windows-Versionen klappt ( Fehler behoben, Programm rechnet genau ).
Jetzt habe ich das Programm auf einem älteren PC laufen lassen (Win XP), und da tritt der Fehler noch immer auf - obwohl der Zahlentyp umgestellt wurde.
Hat da jemand einen Ansatz?
Danke im Vorfeld,
jup
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 03.05.11 12:34
Es ist doch genau. Die Ungenauigkeit merkst du ja nicht, weil die so weit hinter dem Komma durch die interne Darstellung entsteht.
Zur Ausgabe musst du natürlich darauf achten, dass du das dann richtig ausgibst. Stichwort RoundTo oder Format oder... 
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 03.05.11 13:19
|
|
Gammatester
      
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Di 03.05.11 13:46
Und was soll das erklären? Hier wird doch gar nicht auf Gleichheit getestet und es treten keine Rechenfehler auf! Das Ausgangsproblem scheint paradox, weil mit unterschiedlichen Genauigkeiten gerechnet wird und 0.2 halt weder real noch extended exakt darstellbar ist. Das Problem tritt nicht auf zB für 0.125 oder 0.25.
Beispiel mit Dezimalsystem. "Real" = 5 Stellen, "Extended" = 8 Stellen, Rechnung wird "Extended" gemacht:
Quelltext 1: 2: 3:
| x1,x2: real; x1 := 0.33333333; // x1 = 0.333333 x2 := x1 - 0.33333333; // x2 = 0.333333 - 0.33333333 = -0.00000333 |
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 03.05.11 14:15
Es ist doch egal, ob auf Gleichheit getestet wird oder nicht. Lies den Artikel. Da erkläre ich, warum sich manche Dezimalzahlen nicht ein zu eins im Binärsystem abbilden lassen. Und genau das ist das Problem, warum x1:=0.2; x2:=x1-0.2; eben nicht null ergibt.
|
|
Gammatester
      
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Di 03.05.11 14:33
Luckie hat folgendes geschrieben : | Es ist doch egal, ob auf Gleichheit getestet wird oder nicht. Lies den Artikel. Da erkläre ich, warum sich manche Dezimalzahlen nicht ein zu eins im Binärsystem abbilden lassen. Und genau das ist das Problem, warum x1:=0.2; x2:=x1-0.2; eben nicht null ergibt. |
Unsinn! Wie ja schon festgestellt wurde, ist es exakt gleich 0, wenn extended gerechnet wird. Darüber hinaus sind alle Gleitkommadifferenzen x-y exakt, wenn x und y Gleitkommazahlen mit y/2 <= x <= 2*y sind (wenn kein Underflow auftritt). Wenn Du das nicht weißt oder nicht glaubst, suche doch einfach mal nach "Sterbenz Lemma" (Dies ist zB Theorem 11 in D. Goldbergs "What Every Computer Scientist Should Know About Floating-Point Arithmetic", zB via cr.yp.to/2005-590/goldberg.pdf)
|
|
KleinesPferd
      
Beiträge: 29
|
Verfasst: Di 03.05.11 14:37
Es ist eine Eigenschaft von Fließkommazahlen (float), dass sie generell Näherungswerte der uns gebräuchlichen Zahlen sind.
Eine FLOAT besteht aus einem VorzeichenBit, gefolgt von einer Mantisse (oder Basis) und einem Exponenten.
1. Problem: Null-Darstellung
Mathematisch ist
edit weil falsch war:
irgendwas^0
immer 1. Somit ist die Mantisse nie Null. Es bleibt nun übrig, die Basis sehr klein zu wählen, oder den Exponenten entsprechend klein zu machen. -> Führt zu einer Rundung.
2. Problem:
Desweiteren ist es eine Herausforderung, eine Basis UND einen Exponenten zu finden, die genau 0.2 ergeben. Oder Pi, oder jede andere uns geläufige Zahl.
Für uns ist eine Zahl mit 17 mal die 0 als Nachkommastelle eine Null. Für den PC nicht
Grüße
(p.s. alles rein akademisch)
Zuletzt bearbeitet von KleinesPferd am Di 03.05.11 15:17, insgesamt 1-mal bearbeitet
|
|
Gammatester
      
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Di 03.05.11 14:53
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Di 03.05.11 15:01
KleinesPferd hat folgendes geschrieben : | Mathematisch ist 0^(irgendwas) immer 1. |
Meine Schulzeit liegt zwar fast 40 Jahre zurück, aber das kann nicht stimmen, denn 0 * 0 ist 0.
Du meinst wohl "x hoch 0", denn das wäre immer 1 (wenn ich mich noch richtig daran erinnere).
|
|
KleinesPferd
      
Beiträge: 29
|
Verfasst: Di 03.05.11 15:13
Ich seh grad, da hab ich was verwechselt *arg* Besonders weil die Mantisse nie 0 ist, sondern zw 1 und 2.
Ja ich meine x^0 ist 1 ... Ich bitte um Entschuldigung.
Auch wollte ich nicht auf die Feinheiten von Double oder Extended oder sonst was hinaus, sondern den generellen Aufbau einer Fließkommazahl anreißen. Damit der TE nachvollziehen kann, warum dort E-17 steht. Denn nicht jeder der hier im Forum liest und schreibt, ist dem Prinzip Fließkommazahl mächtig. Und nicht jeder der den Text von cr.yp.to überfliegt, versteht auf Anhieb den Sinn dahinter. Wenn jemals die Zeit gefunden wird sich da reinzulesen.
Mag ja sein, das mit extended viele Annehmlichkeiten eingezogen sind. Grundprinzip ist trotzdem geblieben.
Auch wenn dein Hinweis richtig ist, finde ich, das du mit Kanonen auf Spatzen schiesst 
|
|