AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Single wert ist unterschiedlich obwohl gleich
Thema durchsuchen
Ansicht
Themen-Optionen

Single wert ist unterschiedlich obwohl gleich

Ein Thema von EWeiss · begonnen am 17. Jun 2018 · letzter Beitrag vom 19. Jun 2018
Antwort Antwort
Benutzerbild von bernau
bernau

Registriert seit: 1. Dez 2004
Ort: Köln
1.312 Beiträge
 
Delphi 12 Athens
 
#1

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 11:39
Für Gleitkomma-Datentypen verwende ich mittlerweile (fast) immer Funktionen aus der Unit System.Math

IsZero oder Samevalue oder compareValue ist da dein Freund.
Gerd
Kölner Delphi Usergroup: http://wiki.delphitreff.de
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#2

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 11:42
Für Gleitkomma-Datentypen verwende ich mittlerweile (fast) immer Funktionen aus der Unit System.Math

IsZero oder Samevalue oder compareValue ist da dein Freund.
Ja warum es einfach machen wenn es auch umständlich geht.
Bleibt unverständlich für mich.

Zitat:
C++ rechnet wohl immer double (aber legt mich nicht fest).
Delphi-32-Bit rechnet intern mit extended.
Delphi-64-Bit via SSE immer als double.
Jo..
Ich habe schon Anwendungen in Sharp, VBNet, Vb6, C++ geschrieben
Nirgendwo habe ich je solche Probleme mit Single gehabt.

gruss

Geändert von EWeiss (18. Jun 2018 um 11:45 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.588 Beiträge
 
Delphi 12 Athens
 
#3

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 12:03
Ich habe schon Anwendungen in Sharp, VBNet, Vb6, C++ geschrieben
Nirgendwo habe ich je solche Probleme mit Single gehabt.
Und mit welchen Typen?

Je feiner der typ auflöst, also je größer er ist, um so kleiner werden die Problembereiche und so schwerer wird es sie zu treffen.



Beim Unwandeln dieser Werte in eine Textdarstellung sollte man niemals mehr als die signifikanten Stellen umwandeln, da alles danach quasi "zufällig" ist und diesen Rundungsfehler potenziert darstellt, je weiter man dahinter schaut.

Bei Vergleichen, vor allem Gleich, Kleiner-Gleich und Größer-Gleich, aber auch bei Kleiner und Größer muss man eben auch diese Rundungsfehler mit einbeziehen, was eben IsZero oder CompareValue machen (Delta).


Wer unbedingt genaue Werte braucht, muss auch die passenden Typen verwenden, wie z.B. Currency, BCD oder Dergleichen.


@gammatester: Wer mit solch kleinen Werten arbeitet, muß eben entweder das Delta anpassen oder eine andere Vergleichsmethode verwenden.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (18. Jun 2018 um 12:06 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#4

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 12:08
Zitat:
Beim Unwandeln dieser Werte in eine Textdarstellung
Welche Textdarstellung sorry ich sehe keine.

Delphi-Quellcode:
procedure RenderScale(WinHandle: HWND);
var
  bDone: BOOL;
  K, ID: Integer;
  CountMax: Integer;
  x, x1, y, y1, w, h: Integer;
  nScale: Integer;
begin

  bDone := false;
  CountMax := FaceList.Count - 1;

  ID := ID_FACE;

  for K := 0 to CountMax - 1 do
  begin
    if (ID <> gnFocusID) then
    begin
      rScale := gSprFace.GD_GetObjectScale(ID);
      if (ID = nHoverID) then
      begin
        if (rScale < 1.0) then
        begin
          bDone := true; // Wird hier true geschaltet und bleibt True wenn Single wert nicht stimmt.
          rScale := rScale + SCALE_STEP;

          if (rScale > 1.0) then
          begin
            rScale := 1.0;
            bDone := false;
          end;
          // Flare Animation
          gSprFace.GD_GetObjectBound(ID, w, h);
          nScale := (w - round(w * rScale)) div 2;

          gSprFace.GD_SetObjectVisibility(gnFocusFlare, true);

          gSprFace.GD_GetObjectXY(ID, x, y);
          x1 := x + 63 - nScale;
          y1 := nScale + 10;
          gSprFace.GD_SetObjectXY(gnFocusFlare, x1, y1);
          // Weiter mit ID
          gSprFace.GD_SetObjectScale(ID, rScale);
        end;
      end
      else
      begin
        if (rScale > SCALE_DEFAULT) then // stimmt dieser wert nicht dann ist bDone immer true und löst ein Repaint des gesamten Container aus.
        begin
          bDone := true;

          rScale := rScale - SCALE_STEP;
          if (rScale < SCALE_DEFAULT) then
          begin
            rScale := SCALE_DEFAULT;
            gSprFace.GD_SetObjectVisibility(gnFocusFlare, false);
            bDone := false;
          end;

          gSprFace.GD_SetObjectScale(ID, rScale);
        end;
      end;
    end;
    dec(ID);
  end;

  if (bDone) then
    gSprFace.GI_UpdateWindow(WinHandle, false); // Hier Problem wenn Single wert nicht stimmt = 35% CPU Auslastung.
end;
Zitat:
Und mit welchen Typen?
Beatwortet sich von selbst mit Single natürlich.
Wie der Compiler das innerhalb berechnet kann mir letztendlich egal sein.
Die dort verwendeten Compiler scheinen es richtig zu verstehen, Delphi hingegen nicht! (Extra Wurst halt)

gruss

Geändert von EWeiss (18. Jun 2018 um 12:14 Uhr)
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#5

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 12:16
@gammatester: Wer mit solch kleinen Werten arbeitet, muß eben entweder das Delta anpassen oder eine andere Vergleichsmethode verwenden.
Sag ich ja: Wenn man keine Ahnung hat benutzt man die Default-Werte und macht (wie Borland/Emba beim sinh) haarsträubende Fehler. Wenn man weiß, wo die Probleme sind, dann braucht man diese Routinen nicht.

Im übrigen ist 1e-20 geradezu erschreckend groß im Vergleich zu 1e-300 oder 1e-4000.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#6

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 12:27
@gammatester: Wer mit solch kleinen Werten arbeitet, muß eben entweder das Delta anpassen oder eine andere Vergleichsmethode verwenden.
Sag ich ja: Wenn man keine Ahnung hat benutzt man die Default-Werte und macht (wie Borland/Emba beim sinh) haarsträubende Fehler. Wenn man weiß, wo die Probleme sind, dann braucht man diese Routinen nicht.

Im übrigen ist 1e-20 geradezu erschreckend groß im Vergleich zu 1e-300 oder 1e-4000.
Sorry das ich das jetzt sage.. Eigentlich für mich egal.
Was zählt ist das ich eine Lösung wenn auch eine für mich unverständliche gefunden habe.
Ich bin nicht der Informatiker so wie ihr von daher zählt für mich das Ergebnis nicht das was dahinter steckt.

@gammatester
Danke nochmal für deine Hilfe und den Anstoß die Lösung zu finden.
PS: Interessant ist es aber trotzdem zu lesen.

gruss
  Mit Zitat antworten Zitat
Benutzerbild von bernau
bernau

Registriert seit: 1. Dez 2004
Ort: Köln
1.312 Beiträge
 
Delphi 12 Athens
 
#7

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 12:45
Sag ich ja: Wenn man keine Ahnung hat benutzt man die Default-Werte und macht (wie Borland/Emba beim sinh) haarsträubende Fehler. Wenn man weiß, wo die Probleme sind, dann braucht man diese Routinen nicht.
Nur weil man Funktionen ggf. falsch anwenden kann, sind diese trotzdem nicht per se schlecht.

Und ein IsZero(Value1) oder SameValue(Value1,Value2) ist m.E. besser zu lesen als jede hingeklatsche Berechnung, die ein Epsilon berücksichtigt.

Oder gib mal ein Beispiel, wie du zwei Gleitkommazahlen vergleichst. Man lernt ja nie aus.
Gerd
Kölner Delphi Usergroup: http://wiki.delphitreff.de
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#8

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 13:34
Nur weil man Funktionen ggf. falsch anwenden kann, sind diese trotzdem nicht per se schlecht.
Habe ich auch nie behauptet. Was ich gesagt habe, ist, daß sie überflüssig sind und zu Fehlern verleiten, weil gedacht werden könnte, man habe die Probleme der Fließkommaarithmetik damit magisch in den Griff bekommen.
Und ein IsZero(Value1) oder SameValue(Value1,Value2) ist m.E. besser zu lesen als jede hingeklatsche Berechnung, die ein Epsilon berücksichtigt.
Also für mich ist value1=0 oder value1=value2 viel besser lesbar und überhaupt nicht hingeklatscht. Über die Verwantwortung der Programmiers, ob die eine oder die andere Formulierung angemessener ist, wird damit nichts gesagt. Nochmal zu Errinnerung: mit welchem Default-Epsilon arbeitet iszero? (wenn Du es nicht weißt, solltest Du besser die Finger davon lassen). Ich sehe jedenfalls keine Sinn darin, dass const s: single = 0.0001 gleich Null sein soll (gerade mal 1/10 Promille) oder daß iszero(0,-0.00001) ungleich Null liefert.

Oder gib mal ein Beispiel, wie du zwei Gleitkommazahlen vergleichst. Man lernt ja nie aus.
Das Problem ist doch nicht das Vergleichen von Fließkommazahlen, die sind immer exakt und genau definiert. Ein Problem (neben der Tatsache, daß nicht alle reellen Zahlen Fließkommazahlen sind) ist, daß im Laufe von Rechnungen sich Rundungsfehler akkumulieren können, wenn man keine stabilen Algorithmen/Methoden benutzt. Es gibt ein spezielles Fach für solche Sachen (Numerische Mathematik, 'Scientific Computing'), hier erhält Abschätzungen, wie sich Eingangsfehler und Ausgangsfehler verhalten. Erst wenn man die Fehlerschranken der Methode kennt, kann man sinnvoll über die Toleranzen reden.

Leider ist es so, daß es keine Patentlösung gibt, und es nicht hilft, Schulbuchformeln zusammenzustellen und manchmal ein iszero etc einzufügen.

Hier das schon genannte Beispiel aus Math
Delphi-Quellcode:
function Sinh(const X: Extended): Extended;
begin
  if IsZero(X) then
    Result := 0
  else
    Result := (Exp(X) - Exp(-X)) / 2;
end;
Richtiger wäre, if IsZero(X) then Result := x, weil ja für kleine x die Maclaurinreihe für sinh(x) = x +x^3/6 + ... ist. Damit verschenkt man allerdings viel, da iszero hier mit 1e-16 arbeitet. Viel besser und lesbarer ist if abs(x) < 1e-9 then Result := x.

Auch der Rest ist Katastrophe. Warum soll man Exp zweimal aufrufen? Vielleicht um noch ein paar Rundungsfehler mehr zu machen? Entweder ist x so groß, daß exp(-x) vernachlässigbar ist, oder man benutzt exp(-x) = 1/exp(x). Ganz abgesehen davon, daß diese Schulbuchformel instabil ist da anfällig für katastrophale Auslöschung (sie liefert zB 0.999999996004197E-12 statt 1E-12 für sinh(1e-12)).

Geändert von gammatester (18. Jun 2018 um 13:57 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von bernau
bernau

Registriert seit: 1. Dez 2004
Ort: Köln
1.312 Beiträge
 
Delphi 12 Athens
 
#9

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 13:53
Also für mich ist value1=0 oder value1=value2 viel besser lesbar und überhaupt nicht hingeklatscht.
Aber der direkte Vergleich von Gleitkommazahlen ist eben ein NoGo. Genau damit fällt man doch auf die Nase. Du weist doch nicht wie die Zahlen entstanden sind. Ggf. durch komplexe Berechnungen. Dann ist ein value1=0 zufällig mal False, obwohl es true sein sollte. Das Gleiche gilt für value1=value2.

Diese Schreibweise ist natürlich schöner. Bei Integer kein Problem. Aber nicht bei Gleitkommazahlen.
Gerd
Kölner Delphi Usergroup: http://wiki.delphitreff.de
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#10

AW: Single wert ist unterschiedlich obwohl gleich

  Alt 18. Jun 2018, 12:01
IsZero oder Samevalue oder compareValue ist da dein Freund.
Das sind genau die Routinen für Leute, die keine/wenig Ahnung haben. Nach der simplen Methode liefert iszero(Planckkonstante)=true oder iszero(Gravitationkonstante)=true. Außerdem ist iszero für solche Feautures wie sinh(1e-20)=0 verantwortlich, wohingegen sin(1e-20) richtig = 1e-20 ist.
Delphi-Quellcode:
{$apptype console}
uses
  Math;
const
  g: single = 6.67e-11;
  h: extended = 6.63e-34;
begin
  writeln(iszero(g));
  writeln(iszero(h));
  writeln(sinh(1e-20));
  writeln(sin(1e-20));
end.
Code:
TRUE
TRUE
 0.00000000000000E+0000
 1.00000000000000E-0020
Man kann iszero etc richtig verwenden, aber dann kann man auch gleich seine Kenntnisse in die richtige Formulierung stecken. (Wer weiß schon auswendig, welche Default-Toleranz benutzt wird?)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:06 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