Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Rundungsprobleme mit Extended (https://www.delphipraxis.net/154475-rundungsprobleme-mit-extended.html)

TM. 12. Sep 2010 15:51

Delphi-Version: 7

Rundungsprobleme mit Extended
 
Hallo,

ich habe bei meinem Programm eine Menge an Rundungsfehlern; manche kann ich nicht nachvollziehen, möglicherweise hängt das mit Bits und ihrer Funktionsweise zusammen..

Erstens verwende ich FloatToStrF() mit ffFixed, da ich ansonsten eine nicht erwünschte Schreibweise wie "5E-09" bekomme - allerdings kann es sein, dass eine Zahl wie 3,24 nun in 3,23999999.. umgewandelt wird. Mit FloatToStr habe ich dieses Problem nicht, allerdings kann ich das ja nicht verwenden.

Zweitens habe ich einen unerwünschten Rechenfehler, der noch unverständlicher für mich ist. Dabei errechne ich drei verschiedene Werte, die in diesem Fall alle derselbe sind. Mit diesen rechne ich dann:
Delphi-Quellcode:
SSteigung1 := (Steigung2 - Steigung1) / 0.00001;
SSteigung2 := (Steigung3 - Steigung2) / 0.00001;
Nun nimmt SSteigung2 wie erwünscht den Wert '0' an, SSteigung1 dagegen etwas wie '-5,42101..e-10'. Wie kann das sein, da ich ja denselben Rechenschritt ausführe, und wie kann ich es beheben? Ich benutze durchgehend den Typ Extended.

Danke,
TM.

mkinzler 12. Sep 2010 15:56

AW: Rundungsprobleme mit Extended
 
Welche Typen haben die 3 Variablen? Es wird immer mit dem "kleinesten" Typ gerechnet

XHelp 12. Sep 2010 15:57

AW: Rundungsprobleme mit Extended
 
Weist du den Steigungen die Werte per Hand, oder kommen die aus einer Formel?
Generell lässt sich nicht jede Zahl exakt als Gleitkommazahl binär kodieren. Es wird dann der nächstmögliche Wert genommen. Vllt kommt es dadurch zu den Fehlern.

TM. 12. Sep 2010 16:04

AW: Rundungsprobleme mit Extended
 
Hallo,

die drei Variablen haben auch den Typ Extended.
Die Werte kommen aus einer Formel - es könnte natürlich sein, dass die Werte, die es mir während der Laufzeit anzeigt, gerundet sind - also die 1.
Da ich aber zum Testen mit der Funktion 'f(x) = x' arbeite, sollten Steigung1, Steigung2 und Steigung3 auch denselben Wert haben.
Delphi-Quellcode:
Steigung1 := (Calculate(Eingabe, X + 0.00001) - Calculate(Eingabe, X) / 0.00001);
//Anders geschrieben: Steigung := (Y2 - Y1) / (X2 - X1) oder Steigung := (Y(x0 + h) - Y(x0) / h

Satty67 12. Sep 2010 16:13

AW: Rundungsprobleme mit Extended
 
Wenn der nötige Wertebereich nicht zu groß ist (also Gesamtgröße, Anzahl der Nachkommastellen) könntest Du auch mit kleineren Einheiten rechnen und dabei ganz auf Gleitkommazahlen verzichten.

Also als Beispiel (mit Währung):

Statt in Euro, rechnest Du in Cent, wodurch Du nicht 0,25 Euro sondern 25 Cent hast. Wenn es noch genauer sein soll mit 250 Zentel-Cent. Erst am Ende der Berechnung teilst Du das Ergebnis durch 100 oder 1000 um auf die gewünscht End-Einheit (hier Euro) zu kommen.

Integer oder Int64 sind zwar in der Größe begrenzt, können aber alle Werte in Ihrem Wertebreich darstellen.

himitsu 12. Sep 2010 16:31

AW: Rundungsprobleme mit Extended
 
Eventuell wäre auch der Typ Delphi-Referenz durchsuchenCurrency eine Möglichkeit.

Namenloser 12. Sep 2010 16:33

AW: Rundungsprobleme mit Extended
 
Mal was anderes: Ist bei
Delphi-Quellcode:
Steigung1 := (Calculate(Eingabe, X + 0.00001) - Calculate(Eingabe, X) / 0.00001);
nicht eine Klammer falsch gesetzt?
Imo müsste es
Delphi-Quellcode:
Steigung1 := (Calculate(Eingabe, X + 0.00001) - Calculate(Eingabe, X)) / 0.00001;
heißen.

Satty67 12. Sep 2010 16:38

AW: Rundungsprobleme mit Extended
 
Zitat:

Zitat von himitsu (Beitrag 1049057)
Eventuell wäre auch der Typ Delphi-Referenz durchsuchenCurrency eine Möglichkeit.

Ja, wenn ihm 4 Nachkommastellen reichen, hätte der Typ sogar ein paar Vorteile. Gleiche Operatoren wie bei Gleitkomma und nachträgliches Teilen entfällt (ist ja ein INT64, mit festen 4 Nachkomma)

TM. 12. Sep 2010 17:51

AW: Rundungsprobleme mit Extended
 
Hallo,

@NamenLozer: Danke für den Hinweis, da ich aber auf meinem Laptop programmiere, dort aber nicht ins Internet gehe, ist es ein einfacher Abtippfehler. Programmiert ist es richtig.

Mein Wertebereich ist leider ziemlich groß; sowohl vor als auch nach dem Komma, da ich mit Funktionen arbeite. Kann deine Lösung dann immer noch verwendet werden? Da es auch einige Arbeit ist, immer zu multiplizieren/dividieren - gibt es noch einen anderen Weg? 4 Nachkommastellen reichen leider nicht; ich rechne bisher mit mindestens 9-10; Möglicherweise mehr.

Satty67 12. Sep 2010 18:03

AW: Rundungsprobleme mit Extended
 
Int64 hat 18,9 Stellen, die Du dann passend auf Vorkomme/Nachkomma aufteilen könntest.

Allerdings ist die Verwendung der bereitstehenden Funktionen, welche einen Gleitkommawert erwarten, so nicht möglich. Wenn es nur wenige sind... nachbauen?

Ansosnten evtl eine Bibliothek für Wissenschaftliches berechnen suchen. Gibt vielleicht etwas in der Art wie BigInt, wo dann nicht die Probleme mit Standard-Datentypen auftreten


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:05 Uhr.

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