Delphi-PRAXiS
Seite 1 von 4  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   kaufmännisch runden (https://www.delphipraxis.net/177772-kaufmaennisch-runden.html)

rapante 26. Nov 2013 15:53

kaufmännisch runden
 
Hallo,
inder Code-Lib gibt es eine Funktion fürs kaufmännische Runden von shmia:
http://www.delphipraxis.net/50081-ka...ch-runden.html

Leider musste ich fesstellen, dass diese Funktion nicht zuverlässig funktioniert.
Im folgenden Beispiel erhalte ich 2 unterschiedliche Werte (einmal wird ab- und einmal wird aufgerundet):
Delphi-Quellcode:
var
  x,y : Extended;
  resx, resy: Extended;
begin
  y := 17.325;
  resy := RoundX(y,2);

  //ergibt 17.325
  x := ((275 - 27.5) / 100) * 7 ;
  resx := RoundX(x,2);

  showmessage(FloatToStr(resx) + ' | ' + FloatToStr(resy));
end;

function RoundUp(X: Extended): Extended;
begin
   Result := Trunc(x) + Trunc(Frac(x) * 2);
end;

function RoundX(const Value:Extended; const nk:Integer): Extended;
var
   multi: Extended;
begin
   multi := IntPower(10, nk);
   Result := RoundUp(Value*multi) / multi;
end;
Der zweite Trunc-Befehl in RoundUp() gibt 0 anstatt 1 zurück.
Ursache ist wohl die Genauigkeit von Extended. Wie lässt sich das am besten vermeiden?

himitsu 26. Nov 2013 16:12

AW: kaufmännisch runden
 
Seine Funktion funktioniert richtig, aber deine Berechnung rechnet "falsch" => Rundungsfehler

Delphi-Quellcode:
var
  x,y : Extended;
  resx, resy: Extended;
begin
  y := 17.325;
  resy := RoundX(y, 2);
  // ergibt 17.325 .... nein, ergibt 17,324999999999999998...
  // (bzw. 17,324999999999999998265276524023 = 17,325 - 0,00000000000000000173472347597681)
  x := ((275 - 27.5) / 100) * 7 ;
  resx := RoundX(x, 2);

  ShowMessage(FloatToStr(resx) + ' | ' + FloatToStr(resy) + ' | ' + FloatToStr(x - y) + ' = ' + BoolToStr(x = y, True));
end;
Zitat:

---------------------------
Project1
---------------------------
17,32 | 17,33 | -1,73472347597681E-18 = False
---------------------------
OK
---------------------------
Die 2.475, des Ergebnisses von
Delphi-Quellcode:
247.5 / 100
, läßt sich vermutlich binär nicht genau darstellen.

Uwe Raabe 26. Nov 2013 16:25

AW: kaufmännisch runden
 
Nicht unbedingt die überwältigende Performance, aber geht:

Delphi-Quellcode:
 
resx := StrToFloat(Format('%1.*f', [2, x]));

Alternativ hilft manchmal auch ein Zwischenschritt über Currency:

Delphi-Quellcode:
  resz := FloatToCurr(x);
  resz := RoundX(resz,2);

rapante 26. Nov 2013 16:33

AW: kaufmännisch runden
 
Mmmmhh, das blöde ist, das mir aber 17.325 angezeigt werden wenn ich x ausgebe (oder debugge)... Kann man das irgendwo
einstellen?

Den weg über Currency habe ich auch schon in Betracht gezogen. Allerdings bin ich mir nicht sicher ob ich mir damit an anderer
Stelle Probleme einhandele...

himitsu 26. Nov 2013 16:35

AW: kaufmännisch runden
 
Delphi-Quellcode:
  resz := FloatToCurr(x);
  resz := RoundX(resz, 2);

  // dürfte eigentlich Folgendem entsprechen

  resz := RoundX(x, 4); // FloatToCurr(x);
  resz := RoundX(resz, 2);
:gruebel:

Uwe Raabe 26. Nov 2013 16:43

AW: kaufmännisch runden
 
Zitat:

Zitat von himitsu (Beitrag 1237513)
Delphi-Quellcode:
  resz := FloatToCurr(x);
  resz := RoundX(resz, 2);

  // dürfte eigentlich Folgendem entsprechen

  resz := RoundX(resz, 4); // FloatToCurr(x);
  resz := RoundX(resz, 2);
:gruebel:


Nicht ganz:

Delphi-Quellcode:
  resz := RoundX(x, 4); // FloatToCurr(x);
  resz := RoundX(resz, 2);
kommt eher hin.

arnof 26. Nov 2013 20:25

AW: kaufmännisch runden
 
Der Trick ist ganz einfach und gilt für alles was mit FLOAT Typen arbeitet (ob Delphi oder SQL Server) und liegt in der Natur des Aufbaus.

Addiere einfach einen ganz kleinen Wert zu deiner Variablen, die Du Runden willst.

Also z.B.:

x:=Roundx(blablub+0.00000001,2);

Danach werden deine Probleme sich lösen:thumb:

Morphie 26. Nov 2013 20:31

AW: kaufmännisch runden
 
Nur mal aus Interesse: gibt es einen plausiblen Anwendungsfall dafür, eine Fließkommazahl kaufmännisch zu runden? Mir fällt so spontan nämlich keiner ein...

arnof 26. Nov 2013 21:39

AW: kaufmännisch runden
 
Praxis: jede Rechnung, Angebot oder Kassenbon ….

Uwe Raabe 26. Nov 2013 22:07

AW: kaufmännisch runden
 
Vielleicht will Morphie damit aber auch nur sagen, daß für kaufmännische Anwendungsfälle der Datentyp Currency die bessere Wahl ist?


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:03 Uhr.
Seite 1 von 4  1 23     Letzte »    

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