AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

SimpleRoundTo

Ein Thema von MrSpock · begonnen am 24. Dez 2012 · letzter Beitrag vom 29. Dez 2012
Antwort Antwort
Seite 2 von 2     12   
Volker Z.

Registriert seit: 3. Dez 2012
Ort: Augsburg, Bayern, Süddeutschland
419 Beiträge
 
Delphi XE4 Ultimate
 
#11

AW: SimpleRoundTo

  Alt 28. Dez 2012, 19:57
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ß
Miniaturansicht angehängter Grafiken
lokale_variablen.gif   ueberwachte_ausdruecke.gif  
Volker Zeller

Geändert von Volker Z. (28. Dez 2012 um 20:18 Uhr) Grund: Fehlerhafte Angabe korrigiert
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#12

AW: SimpleRoundTo

  Alt 29. Dez 2012, 11:39
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).
  Mit Zitat antworten Zitat
Benutzerbild von MrSpock
MrSpock
(Co-Admin)

Registriert seit: 7. Jun 2002
Ort: Owingen
5.865 Beiträge
 
Delphi 2010 Professional
 
#13

AW: SimpleRoundTo

  Alt 29. Dez 2012, 11:45
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.
Albert
Live long and prosper


MrSpock
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


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 07:27 Uhr.
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