Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   SimpleRoundTo (https://www.delphipraxis.net/172309-simpleroundto.html)

Volker Z. 28. Dez 2012 19:57

AW: SimpleRoundTo
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo,

Zitat:

Delphi-Quellcode:
var
  a: Extended;
begin
   a := 10.175 - 5E-10;
   Caption := FloatToStr(SimpleRoundTo(a));
Der Debugger (Delphi 2007/2010) zeigt a=10,175 an, obwohl der Fehler bereits bei 5E-10 liegt, und damit weit oberhalb der eigentlich erreichbaren Genauigkeit von Extended.
Da foppt uns wohl der Debugger (siehe Anhänge).

Delphi-Quellcode:
var
  f : Double;
  a, b, c : Extended;
begin
  a := 0.55;
  b := 18.5;

  f := IntPower (10, -2);
  c := a * b; // 10.175 in den Lokalen Variablen, 10.175 in Überwachte Ausdrücke
  c := c / f; // 1017.5 in den Lokalen Variablen, aber 1017.49999999999998 in Überwachte Ausdrücke (und damit wird gerechnet)
  c := Trunc (c + 0.5) * f;
end;
Damit: Trunc(1017.99999999999998) = 1017.

Diese Variante
Delphi-Quellcode:
var
  f : Double;
  a, b, c : Double;
begin
  a := 0.55;
  b := 18.5;

  f := IntPower (10, -2);
  c := a * b; // 10.175 in den Lokalen Variablen, 10.1750000000000007  in Überwachte Ausdrücke
  c := c / f; // 10.175 in den Lokalen Variablen, 10.175 in Überwachte Ausdrücke
  c := Trunc (c + 0.5) * f; // 10.18 in den Lokalen Variablen, aber 10.1799999999999997 in Überwachte Ausdrücke

  Caption := FloatToStr (c) // gibt 18,18 aus hier richtet es FloatToStr
end;
Gruß

samso 29. Dez 2012 11:39

AW: SimpleRoundTo
 
Delphi-Quellcode:
  c := Trunc (c + 0.5) * f; // 10.18 in den Lokalen Variablen, aber 10.1799999999999997 in Überwachte Ausdrücke

   Caption := FloatToStr (c) // gibt 18,18 aus hier richtet es FloatToStr
Das ist ja in diesem Fall auch völlig korrekt, weil der Fehler von 3E-16 innerhalb der maximal mit Double erreichbaren Genauigkeit liegt. FloatToStr ist, soweit ich weiß, für eine Genauigkeit von 16 Ziffern ausgelegt, also etwa der Auflösung von Double.
Der Kern des Fehlers könnte in den verschiedenen Rundungsalgorithmen des Debuggers und von SimpleRoundTo liegen. Der Debugger verwendet ja vermutlich das bankersrounding, während das Programm überwiegend SimpleRoundTo verwendet. Dadurch werden die Werte im Debugger anders dargestellt, als programmintern gerechnet wird und es kommt vielleicht vermeintlich zu einem falschen Ergebnis. Bei den überwachten Ausdrücken wird erfreulicherweise anscheinend der Gleitkommawert komplett dekodiert und nicht ein bereits gerundeter Wert. Es wäre spannend mit dieser Erkenntnis nochmal Mult3 zu debuggen.

MrSpock führt ja aus, dass bei Ihm die Funktion DecimalRoundExt schließlich den Fehler beseitigt hat. Diese Funktion unterscheidet sich von SimpleRoundTo im Wesentlichen dadurch, dass vor dem Runden ein Fehleraufschlag dazu addiert wird. Das bedeutet aber lediglich, dass ein wenig früher nach oben gerundet wird (statt ab 0,005 dann schon ab 0,004999..). Das ist aber nur sinnvoll, wenn man der Auffassung ist, dass es in der vorherigen Berechnung einen konstanten Fehler nach unten gibt (also das Ergebnis von Mult3 stets eher zu klein ist) und keinen zufällig verteilten Fehler. Warum sollte das Ergebnis der Division durch 1E9 immer nach unten vom korrekten Wert abweichen? Bei Gleitkommaberechnungen würde ich aber normalerweise von einem zufällig verteilten Fehler ausgehen (u.a. eben wegen des voreingestellten bankersroundings).

MrSpock 29. Dez 2012 11:45

AW: SimpleRoundTo
 
Ich nutze DecimalRoundExt nicht mit dem Standardwert als "control", sondern mit drHalfUp. Damit habe ich den Effekt, den ich möchte. Zumindest in den Testfällen, die ich benutzt habe. Jetzt muss ich noch die Reaktion des Kunden abwarten, ob im operationellen Einsatz auch kein Cent-Fehler mehr auftritt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:34 Uhr.
Seite 2 von 2     12   

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