Autor |
Beitrag |
Tobias1
Beiträge: 454
Win 98, XP Prof
D3 Prof, D2005 Prof
|
Verfasst: Mi 01.06.05 13:43
Wenn ich mit real werten rechne kommt es vor das es anstatt mit 4 mit 3,9999956 oder so rechnet.
Warum ist das so? Muss ich immer den Wert 4,000000 zuweisen?
Gibt es ein Befehl oder einen anderen Variablentyp, der das behebt?
Danke!
_________________ Auch das schlechteste Buch hat seine gute Seite: die letzte. (John Osborne)
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 01.06.05 13:49
Rundungsungenauigkeit, die darin begründet liegt, wie Fließkommazahlen im Speicher abgelegt werden.
|
|
Gausi
Beiträge: 8535
Erhaltene Danke: 473
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mi 01.06.05 13:50
Hallo,
Das hat mehrere Ursachen. Zum einen ist generell die Rechengenauigkeit im Rechner beschränkt. Einige Rechenoperationen sind dabei so bösartig, das sich diese Ungenauigkeiten extrem hochschaukeln. Ein Beispiel für Matrizen ist dabei die Hilbertmatrix. Sie ist zwar invertierbar, aber durch ihre Struktur kommen beim Berechnen der Inversen komplett andere Werte heraus, als man erwarten würde.
Zum anderen lassen sich auch "ganz normale Zahlen" wie z.B. 0.1 im Binärsystem überhaupt nicht exakt darstellen. Auch da arbeitet der PC dann mit Näherungswerten.
So kommt es, dass einige Rechnungen bisweilen Fehler aufweisen. Ein so großer Fehler ist aber schon merkwürdig. Was berechnest du denn in deinem Beispiel?
_________________ We are, we were and will not be.
|
|
jasocul
Beiträge: 6386
Erhaltene Danke: 146
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Mi 01.06.05 13:50
Tobias1 hat folgendes geschrieben: | Wenn ich mit real werten rechne kommt es vor das es anstatt mit 4 mit 3,9999956 oder so rechnet.
Warum ist das so? Muss ich immer den Wert 4,000000 zuweisen?
Gibt es ein Befehl oder einen anderen Variablentyp, der das behebt? |
1. Weil der PC im Binärsystem rechnet und nicht, wie wir, im Dezimalsystem.
2. Du könntest due Funktion Round benutzen (siehe OH).
3. Meines Wissens nicht. Außer du benutzt Integer. Dann hast du aber keine Nachkommstellen.
|
|
deccer
Beiträge: 57
|
Verfasst: Mi 01.06.05 13:51
<senf>
auf real sollte man verzichten, da es "veraltet"/"deprecated" ist, stattdessen nimmst lieber
single (einfache genauigkeit), oder double (doppelte genauigkeit) - die genauigkeit bezieht sich auch wieder auf die nachkommastellen
</senf>
@forumscheffs - mir fehlt son "Senf" button im editfenster P:
|
|
BenBE
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 01.06.05 17:23
Naja, Auf Single und Double sollte er dann getrost verzichten, wenn ihm Real (=Double unter Delphi) schon Probleme macht.
Versuch Dein Glück mal mit Extended (10 Byte), der zwar etwas mehr Code für die CPU bedeutet, aber genauere Ergebnisse liefert und intern schneller verwendet werden kann (da natives Format der FPU).
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Tobias1
Beiträge: 454
Win 98, XP Prof
D3 Prof, D2005 Prof
|
Verfasst: Mi 01.06.05 17:29
Danke!
_________________ Auch das schlechteste Buch hat seine gute Seite: die letzte. (John Osborne)
|
|
alzaimar
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Mi 01.06.05 17:30
Und wer richtig genau werden will, nimmt BCD. Das kann wenigstens 0.1 100% genau darstellen. Leider sind Floatingpoint Operationen sehr viel schneller als BCD, weswegen in den FPU nur floats benutzt werden, was dann den eingangs zitierten Effekt hat.
Immer wieder gern gesehen (1x form, 1x Button, 3xMemo):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| procedure TForm3.Button1Click(Sender: TObject); Var e: Extended; s : single; r : Real; begin e:= -1; s:= -1; r:= -1; while r<0.2 do begin memo1.lines.add (FloatToStr(e)); memo2.lines.add (FloatToStr(s)); memo3.lines.add (FloatToStr(r)); r := r+0.1; e := e+0.1; s := s+0.1; End; end; |
|
|
Gausi
Beiträge: 8535
Erhaltene Danke: 473
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mi 01.06.05 17:41
alzaimar hat folgendes geschrieben: | Und wer richtig genau werden will, nimmt BCD. Das kann wenigstens 0.1 100% genau darstellen. |
Nur mal aus Neugierde: Was ist/sind BCD, und wie wird damit im Rechner 0.1 genau dargestellt?
_________________ We are, we were and will not be.
|
|
BenBE
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 01.06.05 18:43
BCD = Binary Coded Decimals...
Da werden einfach die Ziffern der Dezimal-Darstellung als Nibbels eines Bytes gespeichert.
25d --> $25 * 100 ^ 0bcd.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
delfiphan
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Fr 03.06.05 00:29
Tobias1 hat folgendes geschrieben: | Wenn ich mit real werten rechne kommt es vor das es anstatt mit 4 mit 3,9999956 oder so rechnet.
Warum ist das so? Muss ich immer den Wert 4,000000 zuweisen?
Gibt es ein Befehl oder einen anderen Variablentyp, der das behebt?
Danke! |
Die Zahl 4 sollte dir eigentlich keine Schwierigkeiten bereiten. Sie ist mit Floats exakt darstellbar. Wenn du die Zahl aber mit einer anderen, ungenaueren Zahl verknüpfst, dann kann es schon vorkommen, dass die Zahl dann nicht mehr genau stimmt. Was für eine Rechnung führst du durch?
|
|
Tobias1
Beiträge: 454
Win 98, XP Prof
D3 Prof, D2005 Prof
|
Verfasst: Fr 03.06.05 07:53
Division, Multiplikation
_________________ Auch das schlechteste Buch hat seine gute Seite: die letzte. (John Osborne)
|
|
alzaimar
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Fr 03.06.05 08:17
Dafür gibt es die Schutzstellen: Du rechnest intern (z.B.) mit voller Genauigkeit und nimmst in Kauf, das eben anstatt mit 4.0000 mit 3.9999996 gerechnet wird. Bei Division und Multiplikation wird sich der Fehler i.A. (hier wörtlich zu verstehen) nicht hochschaukeln. Aber Vorsicht bei Iterationen etc.
Dein Ergebnis stellst Du aber nicht mit voller Genauigkeit dar. Im richtigen Leben reichen normalerweise 4 Stellen aus. Alles Andere ist Quark. Beispiel Abmessungen: Es ist interessant, das z.B. die berechnete Länge 4,56786 m ist, aber das ist doch völlig Schnurz, weil im Meter-Bereich normalerweise nur auf mm genau gemessen wird. Wichtig ist, mit Augenmaß und Drang zur Realität die Genauigkeit anzugeben.
Ich würde Extended-Zahlen nehmen und nie auf Gleichheit prüfen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| Var a,b : Extended;
Begin a := 8.9; b := 4.9; If a-b = 4 Then Showmessage('Foo'); If Abs (4 - (a-b)) < 1E10 Then Showmessage('Bar'); If IsZero (4 - (a-b)) Then Showmessage ('Bar 2'); End; |
Ob hier 'Foo' angezeigt wird, weiss nich nicht. Aber 'Bar' wird in jedem Fall angezeigt, 'Bar 2' auch.
Im Umgang mit reelen Zahlen wirst Du immer mit Schutzstellen arbeiten, also die letzten paar Stellen ignorieren.
|
|
deccer
Beiträge: 57
|
Verfasst: Fr 03.06.05 09:10
BenBE hat folgendes geschrieben: | Naja, Auf Single und Double sollte er dann getrost verzichten, wenn ihm Real (=Double unter Delphi) schon Probleme macht.
Versuch Dein Glück mal mit Extended (10 Byte), der zwar etwas mehr Code für die CPU bedeutet, aber genauere Ergebnisse liefert und intern schneller verwendet werden kann (da natives Format der FPU). |
aha, aber dann nur wenn er mit dem FPU asmbefehlssatz arbeitet, ansonsten weiß ja der compiler nicht, obber jetz die fpu oder cpu bemühen soll
|
|
delfiphan
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Fr 03.06.05 09:27
Darf ich trotzdem nochmal fragen, was du genau berechnen möchtest (evtl. Source?). Vielleicht lässt sich das Problem umschreiben... (Vielleicht auch nicht)
|
|
Stefan.Buchholtz
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: Fr 03.06.05 09:29
deccer hat folgendes geschrieben: | BenBE hat folgendes geschrieben: | Naja, Auf Single und Double sollte er dann getrost verzichten, wenn ihm Real (=Double unter Delphi) schon Probleme macht.
Versuch Dein Glück mal mit Extended (10 Byte), der zwar etwas mehr Code für die CPU bedeutet, aber genauere Ergebnisse liefert und intern schneller verwendet werden kann (da natives Format der FPU). |
aha, aber dann nur wenn er mit dem FPU asmbefehlssatz arbeitet, ansonsten weiß ja der compiler nicht, obber jetz die fpu oder cpu bemühen soll |
Da alle x86er-Prozessoren ab dem 486er aufwärts eine FPU integriert haben, benutzt der Delphi-Compiler (und auch alle anderen mir bekannten aktuellen Compiler) für Fließkommaoperationen immer FPU-Befehle.
Stefan
|
|
deccer
Beiträge: 57
|
Verfasst: Fr 03.06.05 09:38
warum rechnest das nich einfach auf ganze zahlen hoch?
4,123123 * 100000 = 4123123 ..... damit lässts sich "einfacher" rechnern
_________________ I <3 PeRLe
|
|
jasocul
Beiträge: 6386
Erhaltene Danke: 146
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Fr 03.06.05 09:46
Ich benutze im Zweifel immer Round.
Auf Ganzzahlen hochrechnen kann schnell zu Problemen führen. Du weißt ja nicht, wieviele Nachkommastellen zu berücksichtigen sind. Wenn du dann noch zuviele Vorkommastellen hast, gibt es sehr lustige Effekte.
|
|
deccer
Beiträge: 57
|
Verfasst: Fr 03.06.05 10:00
das is klar :)
aber in den meisten fällen hatmer ja nich mehr als 5 oder 6 nachkommastellen (z.b. bei opengl krams) wenn man da nen epsilon oder so brauch .......
naja was solls </senf>
_________________ I <3 PeRLe
|
|
Tobias1
Beiträge: 454
Win 98, XP Prof
D3 Prof, D2005 Prof
|
Verfasst: Fr 03.06.05 13:36
Ich habe jetzt recht viele round-Funktionen,damit gehts, in meinem Code.
Ich wills jetzt aber auf Integer umproggen.
_________________ Auch das schlechteste Buch hat seine gute Seite: die letzte. (John Osborne)
|
|