![]() |
Delphi-Version: 11 Alexandria
Berechnungen mit Gleitkomma Werten
Hallo Liebe Community,
ich habe mir in einer Klassifizierung von Farbwerten ein Dictionary angelegt um diverse Werte schneller ermitteln zu können, dabei bin ich über ein Problem mit Gleitkomma Werten gestolpert. Bei der Addition von Gleitkomma Werten der unterschiedlichen Typen(Single, Double, Real) scheint es zu einem Fehler kommen. Um diesen zu verifizieren habe ich mir ein kleines Test Programm geschrieben, dieses beinhaltet den folgenden Code.
Delphi-Quellcode:
Im Debug Fenster werden bei dieser Operation abweichende zwischen Werte angezeigt.
program FloatTest;
{$APPTYPE CONSOLE} {$R *.res} uses System.Classes, System.SysUtils; var AExtended: Extended; AReal: Real; ADouble: Double; ASingle: Single; i: Integer; begin try AList := TStringList.Create; AExtended := -1.0; ADouble := AExtended; ASingle := ADouble; ASingle := -1.0; AReal := AExtended; for i := 0 to 200 do begin AExtended := AExtended + 0.01; ADouble := ADouble + 0.01; ASingle := ASingle + 0.01; AReal := AReal + 0.01; end; i := 0; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Bsp.: Name des Ausdrucks Wert AExtended -0,42 ASingle -0,420000553131104 ADouble -0,419999999999999 AReal -0,419999999999999 Beim Single Wert ist das Ganze ständig verschoben und schon bei der Wert Zuweisung von Double zu Single verändern sich die Nachkommastellen. Für mich stellt sich jetzt die Frage ob dies ein generelles Delphi Problem ist oder ob dies vllt. an meiner Umgebung liegt. Dieser Zustand tritt im 64-Bit sowie in 32-Bit Windows 11 Umgebungen auf. |
AW: Berechnungen mit Gleitkomma Werten
Die "normalerweise" verwendeten Fließkommazahlen auf üblichen Computersystemen folgend dem "IEEE 754"-Standard. Kleine Ungenauigkeiten sind hier normal.
Wir reden hier ja wirklich über die 6. oder 7. Stelle hinter dem Komma. Das ist normal. Vielleicht schaust du mal bei der Internet-Suchmaschine deines Vertrauens zu "IEEE 754", das ist eigentlich sogar recht interessant wie das funktioniert. |
AW: Berechnungen mit Gleitkomma Werten
Damit umzugehen ist eben die Kunst.
Bei Vergleichen nutzt man sowas wie Samevalue, CompareValue usw. Ggf muss man auch runden. |
AW: Berechnungen mit Gleitkomma Werten
Beim Single schien mir die Abweichung etwas zu hoch zu sein, aber nach weiterem forschen bin ich auf die folgende Seite gestoßen die es wirklich gut erklärt.
![]() |
AW: Berechnungen mit Gleitkomma Werten
Generell solltest Du versuchen überall den gleichen Typ zu verwenden. Beim Umrechnen zwischen Typen kommt es zu Fehlern.
Oder Du verwendest einen Numeric Typen bei dem intern gar keine Gleitkommazahlen verwendet werden. Ich habe das vor Jahren mal probiert, fand es aber fürchterlich langsam. |
AW: Berechnungen mit Gleitkomma Werten
Bei bis zu 4 Nachkommastellen Currency (ist intern ein Int64, der durch 10000 geteilt ist).
![]() Ansonsten gäbe es noch BCD-Typen und Anderes. Oder eben vor Anzeige immer auf die gewünschten Stellen runden/formatieren, sowie Vergleiche niemals mit
Delphi-Quellcode:
, sondern z.B.
=
![]() ![]() ![]() Und für das Dictionary einen passenden Comparer schreiben, falls die "Floats" als Key benutzt werden sollen. Auch nicht fortlaufend draufrechnen ... damit vervielfacht man nur noch die Rundungsfehler. z.B. so
Delphi-Quellcode:
bzw.
for i := 0 to 200 do begin AExtended := -1.0 + (0.01 * i);
Delphi-Quellcode:
ist der Fehler nur zweieinmal enthalten.
:= -1.0 + (i / 100);
Zitat:
dort wird die Ungenauigkeit nur aktuell gerade zufälig erst irgendwo nach der 15. Nachkommastelle liegen (er hat schließlich 19-20 signifikante Stellen, ab der ersten Ziffer, welche nicht 0 ist) |
AW: Berechnungen mit Gleitkomma Werten
Moinsen,
gerade bei Farbwerten würde ich eher auf "RGB" kodierte Integerwerte gehen. Dann hast du keine Probleme mit "Abweichungen" durch Fliesskommadarstellung. Vielleicht kannst du nochmal dein Problem mit der "Klassifizierung von Farbwerten" etwas näher erläutern... Gruß |
AW: Berechnungen mit Gleitkomma Werten
Schon die Konstante 0.01 aus dem Beispielcode lässt sich binär nicht exakt darstellen. Durch das Aufaddieren in der Schleife wird die Abweichung dann immer größer.
Deshalb sollte man genau das vermeiden. Es ist kein spezifisches Delphi-Problem. Vielleicht kannst Du darstellen, was Du eigentlich vorhast, dann lässt sich besser beurteilen, wie man die Abweichungen minimiert. |
AW: Berechnungen mit Gleitkomma Werten
Danke für eure zahlreichen antworten, mir war nicht bewusst das die Abweichung beim Single so groß ist. Für das Erstellen des Dictionaries(Farb und Werte Zuordnung) runde ich einfach nach jeder Addition und das reicht erstmal aus. Mir ging es hier hauptsächlich um die Daten Typen und ich kann jetzt je nach Fall meine internen Berechnung darauf anpassen. Das wird darauf hinaus lauf das ich nur mit Integer/Int64 rechne und erst am Ende auf eine Gleitkomma Zahl um schwenke, denn so sollte sich der Fehler reduzieren lassen.
|
AW: Berechnungen mit Gleitkomma Werten
Eigentlich sollte Extended auch nie zum Speichern verwendet werden (war nur für Zischenschritte von Berechnungen gedacht).
Außerdem ist der Typ nicht überall verfügbar, z.B. nicht unter Win64 oder iOS/Android ... dort ist es intern ein DOUBLE (und belegt überall auch noch unterschliedlich viel Speicher > SizeOf) Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:21 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-2025 by Thomas Breitkreuz