Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Berechnungen mit Gleitkomma Werten (https://www.delphipraxis.net/214657-berechnungen-mit-gleitkomma-werten.html)

itblumi 16. Feb 2024 10:18

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:
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.
Im Debug Fenster werden bei dieser Operation abweichende zwischen Werte angezeigt.
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.

Der schöne Günther 16. Feb 2024 10:50

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.

Jens01 16. Feb 2024 11:01

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.

itblumi 16. Feb 2024 11:25

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.

https://bernd-leitenberger.de/genaui...omputern.shtml

Sinspin 16. Feb 2024 11:36

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.

himitsu 16. Feb 2024 11:42

AW: Berechnungen mit Gleitkomma Werten
 
Bei bis zu 4 Nachkommastellen Currency (ist intern ein Int64, der durch 10000 geteilt ist).
http://docwiki.embarcadero.com/RADSt...hi)#Real_Types

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. Delphi-Referenz durchsuchenIsZero, Delphi-Referenz durchsuchenSameValue, Delphi-Referenz durchsuchenComparaValue usw.
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:
for i := 0 to 200 do begin AExtended := -1.0 + (0.01 * i);
bzw.
Delphi-Quellcode:
:= -1.0 + (i / 100);
ist der Fehler nur zweieinmal enthalten.


Zitat:

AExtended -0,42
PS: Extended ist garantiert auch nicht genau 0,42
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)

noisy_master 16. Feb 2024 11:44

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ß

gubbe 16. Feb 2024 12:28

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.

itblumi 16. Feb 2024 13:30

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.

himitsu 16. Feb 2024 13:54

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:

Dieser Zustand tritt im 64-Bit sowie ... auf
Dort sollten also Double und Extended das Gleiche anzeigen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:05 Uhr.
Seite 1 von 2  1 2      

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