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/)
-   -   Auf 2 stellen Runden (https://www.delphipraxis.net/102397-auf-2-stellen-runden.html)

Kuster Peter 28. Okt 2007 16:13

Re: Auf 2 stellen Runden
 
Liebe Delphianer

Meine Antwort oben tönt beim Durchlesen etwas hochnäsig. Sorry, das will ich nicht, im Gegenteil, Eure Tipps sind echt gut und ich habe wieder viel gelernt, z.B. dass man Math in die Uses Anweisung einbeziehen muss etc. Alles Sachen, die mir in Zukunft helfen. Wirklich vielen Dank.

Stolz bin ich, weil ich eine Lösung gefunden habe, die einfach ist, die man ohne zusätzliche Anweisungen anwenden kann und die 100 % funktioniert und dass ich das erste Mal eine Lösung beisteuern konnte, auch wenn ich die Frage aufgeworfen habe, doch der Eddy hat das Problem auch.

Also meine Antwort nicht flasch verstehen.

Delphi gefällt mir immer besser und ich weine dem Fox bald keine Träne mehr nach!!

Ich wünsche allen eine schöne Woche.

Peter

grenzgaenger 28. Okt 2007 17:08

Re: Auf 2 stellen Runden
 
tja, für die 5 rappen rundung haste recht. aber das andere, kannst du dir sparen, das geht so..

Delphi-Quellcode:
CurrToStrF(12.355, ffFixed, 2)
PS: Peter, du verwendest auch das bankers rounding. kannst mal ausprobieren:
Delphi-Quellcode:
 writeln('Round 12.5: ', round(12.5));
 writeln('Round 13.5: ', round(13.5));
denke, da kommt 'n anderes ergebnis raus, wie du gerne möchtest

eddy 30. Okt 2007 11:22

Re: Auf 2 stellen Runden
 
Hallo Leute,

das Stichwort "bankers rounding" hat's gebracht, man muß eben wissen, wonach man suchen muß!

Allerdings kommt "bankers rounding" mit jedem Taschenrechner in Konflikt. Und auf einer Rechnung sollten die Zahlen nun mal stimmen und nicht von der Berechnung mit einem Taschenrechner abweichen. Egal welche logische oder historische Erklärung es für die Abweichung gibt.

Das mathematischen Runden liefert ein Ergebnis, das ein Taschenrechner auch her gibt.

Delphi-Quellcode:
//liefert auf nk-Stellen mathematisch gerundete Zahl r zurück
// MathRound <--> bankers rounding nur bei 0.005
function mround(r : double; nk : integer = 2) : double;
var
  diff,
  r2,
  multi: double;
begin
  r2 := abs(r);
  multi:=IntPower(10, nk);     // uses Math
  diff := Frac(r * multi);     // Nachkommaanteil von r
  // if diff = 0.5 versagt wg. exponentiell kleiner Abweichungen
  if round(diff * multi) / multi = 0.5
    then r2 := r2 + 0.01 / multi;
  if r >= 0
    then Result := round(r2 * multi) / multi
    else Result := -round(r2 * multi) / multi;
end;
mfg
eddy

Gorlo 12. Okt 2017 10:14

AW: Auf 2 stellen Runden
 
@eddy

Achtung diese Rundungsfunktion ist nicht das eine und nicht das andere. Sie funktioniert NICHT.

Sie ist bei zahlen mit mehr nachkommastellen als die auf der gerundet werden soll falsch.
Beispiel:
mround(0,014, 2) = 0,01
mround(0,01498, 2) = 0,02

PS: Ich kram diesen Thread deswegen wieder raus da er mir bei einer Suche nach Mathematischen runden in Delphi als erstes angezeigt wird und diese Funktion somit falsch verbreitet werden könnte.

sakura 12. Okt 2017 11:28

AW: Auf 2 stellen Runden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Um das Ganze abzuschließen, hier sind gleich mehrere Annahmen falsch.

Beim Banker's Rounding gibt es eine weitere Regelung für den Fall 0.5.

Zusammengefasst:
  • Alle Fälle außer 0.5 verhalten sich identisch zum mathematischen Runden, welches auch in Delphi angewandt wird
  • 0.5 wird im normalen Banker's Rounding immer zur nächsten geraden Zahl gerundet
  • Alternativ wird 0.5 aufgerundet.
Folgender Code deckt genau dieses Verfahren ab, wobei der letzte Parameter für True die Rundung in Richtung gerade durchführt und bei False immer aufrundet.
Delphi-Quellcode:
function BankersRound(const aValue: Double; const aRoundTo: Integer = 2; const aApplyEvenRoundRule: Boolean = True): Double;
var
  PositiveValue,
  IsEven
    : Boolean;
  MultipliedValue,
  FracValue,
  ResolutionDirection
    : Double;
const
  DOUBLE_RESOLUTION = 1E-12;
begin
  if aValue = 0 then
    Exit(0);

  MultipliedValue := Abs(aValue) * IntPower(10, aRoundTo);
  FracValue := Frac(MultipliedValue);

  if not System.Math.SameValue(FracValue, 0.5, DOUBLE_RESOLUTION) then
    Exit(System.Math.RoundTo(aValue, 0 - aRoundTo));

  PositiveValue := aValue > 0;

  if aApplyEvenRoundRule then
  begin
    IsEven := Trunc(MultipliedValue) mod 2 = 0;

    if PositiveValue and IsEven then
      // > 0 and even
      ResolutionDirection := -1
    else if PositiveValue then
      // > 0 and odd
      ResolutionDirection := 1
    else if IsEven then
      // < 0 and even
      ResolutionDirection := 1
    else
      // < 0 and odd
      ResolutionDirection := -1
  end
  else
  begin
    if PositiveValue then
      ResolutionDirection := 1
    else
      ResolutionDirection := -1;
  end;

  Result := System.Math.RoundTo(aValue + ResolutionDirection * DOUBLE_RESOLUTION, -2);
end;
Das gesamte Beispiel inkl. Testfälle ist im Anhang.

...:cat:...

Gorlo 12. Okt 2017 14:45

AW: Auf 2 stellen Runden
 
Dazu nochmal begriff Klarstellung:
Banker's Rounding = Mathematisches Runden
Unser in der schule gelerntes Runden ist das Kaufmännische Runden.
(https://de.wikipedia.org/wiki/Rundung)

In Delphi(5-7) (andere Versionen kann ich gerade nicht nachschauen) nutzt die normale Rundungsfunktion leider das Banker's Rounding (Mathematische Runden).
Fakt ist ICH benötige das Kaufmännisches Runden (für Rechnungen (Einzelpreise 5 stellig da unter 1 Cent somit kein Currency möglich)) und das ist in Delphi(5-7) so nicht einfach möglich.
Auch aus dem Grund da die Double nicht genau genug sind.

Beispiel getestet in Delphi 6:
RoundTo(2194.825, -2) = 2194.82 | Benötigt wird aber 2194.83
Ich habe somit eine Funktion gebaut die mir den wegfallenden Dezimalwert in ein Integer umwandelt den ich dann auf 0-4 bzw. 5-9 prüfen kann. Diese Funktion prüfe ich gerade ob diese auch so funktioniert wie sie soll (was ohne Referenz schwer ist).


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:33 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