Delphi-PRAXiS

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?

sx2008 26. Nov 2013 23:14

AW: kaufmännisch runden
 
siehe Code-Library: http://www.delphipraxis.net/46397-cu...ch-runden.html

himitsu 27. Nov 2013 00:19

AW: kaufmännisch runden
 
Zitat:

Zitat von sx2008 (Beitrag 1237557)

Ich kann mich täuschen, aber für mich sieht das eher wie mathematisches Runden aus und nicht wie das Kaufmännische. :gruebel:

Morphie 27. Nov 2013 05:31

AW: kaufmännisch runden
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1237551)
Vielleicht will Morphie damit aber auch nur sagen, daß für kaufmännische Anwendungsfälle der Datentyp Currency die bessere Wahl ist?

Genau so ist es ;-)

Furtbichler 27. Nov 2013 07:06

AW: kaufmännisch runden
 
Allgemein wird in der praktischen Anwendung technisch-wissenschaftlicher Auswertung mit Augenmaß hantiert. Das bedeutet, das 3-4 (seltener 5) signifikante Stellen als vollkommen ausreichend erachtet werden, um Kenngrößen darzustellen. 3-4 Stellen bedeutet eine Genauigkeit von 2% - 0.2%. Und das entspricht im wahrsten Sinne des Wortes dem maximal möglichen Augenmaß.

Currency kann hier geeignet sein, muß aber nicht (wegen der festen 4 Nachkommastellen). Man kann schon mit Double/Extended arbeiten und die Ungenauigkeiten des Datentyps in Kauf nehmen, denn diese bewegen sich i.A. weit jenseits der geforderten Darstellungsgenauigkeit. Sofern man also keine aufwändigen Iterationen betreibt oder sich in der Atomphysik tummelt (wo mit sehr großen und sehr kleinen Zahlen hantiert wird), kann man sich auf Double verlassen. Iterationen würden die Rundungsungenauigkeiten 'nach links verschieben' und beim Rechnen mit sehr großen und (absolut) sehr kleinen Zahlen passiert das Gleiche.

Man muss nur wissen, das Vergleichsoperationen immer im Kontext der Genauigkeit durchgeführt werden müssen, in der man sich gerade befindet.

Bei Geldbeträgen ist die geforderte Genauigkeit 1 Cent. Ergo werde ich auf 2 Stellen nach dem Komma runden und Vergleiche so formulieren, das die Ungenauigkeit von 0.5 ct berücksichtigt wird. Also ist ein Wert 0.00$, wenn er kleiner als 0.005$ ist (absolut), und A>B genau dann, wenn A-B > 0.005 ct ist usw. Das reicht vollkommen aus.

Bei der Berechnung von Zinsen, Steuern usw. wird gemäß den Vorgaben des Finanzamts auf Centbeträge gerundet. Wenn nach dem Runden die o.g. Vergleichslogik angewandt wird, kann nichts passieren. Pfennigfuchser können noch den arnof-Trick verwenden, der zwar innerlich wehtut, aber genau die datentypbedingte Ungenauigkeit bedingt, mit der man (im Übrigen in allen Programmiersprachen, die Fließkommazahlen verwenden) leben muss.

Eine Alternative dazu ist der Datentyp 'Currency', der jedoch einen limitierten Wertebereich besitzt und fest vier Nachkommastellen hat. Dafür rechnet man damit punktgenau. Für jegliche Geldberechnungen sollte dieser Datentyp ausreichen, denn 50 Stellen reichen für sämtliches auf der Welt befindliche Geld, egal in welcher Währung.

Allgemein gesehen wäre der BCD-Datentyp hier ideal, aber soweit ich das sehe, existiert hier kein nativer Datentyp in Delphi (in C# existiert 'decimal'). Allerdings kann man sich mit Klassen behelfen, die mit beliebig großen Zahlen umgehen können.

MrSpock 27. Nov 2013 07:27

AW: kaufmännisch runden
 
Ich hatte vor einiger Zeit auch einen lästigen Rundungsfehler und das hat mir geholfen.

arnof 27. Nov 2013 08:30

AW: kaufmännisch runden
 
Egal welche Datentypen man verwendet oder das benutzte System bietet, wenn man eine Kleinigkeit hinzuaddiert, so bekommt man das Floatproblem in den Griff.

Zur Info für die Allgemeinheit: alle Floattypen sind nur Näherungswerte und aus 0.015 (was gerundet dann 0.02 währe kann schon mal im echten Leben folgendes werden:

0.014999999 was gerundet nun mal 0.01 ergibt.

Das ist schon großen Firmen passiert :lol:

rapante 27. Nov 2013 09:47

AW: kaufmännisch runden
 
Vielen Dank an alle die Licht ins Dunkel gebracht haben!
Ich habe mich jetzt erstmal für die Lösung von MrSpock entschieden.

Merke: 1 ist nicht immer gleich 1 ;)

JasonDX 27. Nov 2013 10:38

AW: kaufmännisch runden
 
Zitat:

Zitat von arnof (Beitrag 1237573)
Egal welche Datentypen man verwendet oder das benutzte System bietet, wenn man eine Kleinigkeit hinzuaddiert, so bekommt man das Floatproblem in den Griff.

Besser gesagt: man kann damit das Problem an einen anderen Ort verschieben, von dem man dann hofft, dass man dort nie vorbeikommt.
Ja, wenn 0.015 rauskommen sollte, das aber durch 0.01499999 approximiert wird, dann passt die Lösung mit +epsilon. Was aber wenn das Ergebnis der Rechnung 0.01499999 ist? Dann wird das Ergebnis verfälscht, weil auf 0.02 gerundet wird, obwohl 0.01 korrekt wäre.
Egal unter welchen Umständen man Gleitkommazahlen verwendet, es wird immer Probleme geben wenn man genaue Kommastellen braucht. Die einzige Lösung ist, einen für das Problem passenden Datentyp zu verwenden. (Siehe auch Furtbichlers Antwort)

arnof 27. Nov 2013 13:28

AW: kaufmännisch runden
 
Zitat:

Zitat von JasonDX (Beitrag 1237593)
Zitat:

Zitat von arnof (Beitrag 1237573)
Egal welche Datentypen man verwendet oder das benutzte System bietet, wenn man eine Kleinigkeit hinzuaddiert, so bekommt man das Floatproblem in den Griff.

Besser gesagt: man kann damit das Problem an einen anderen Ort verschieben, von dem man dann hofft, dass man dort nie vorbeikommt.
Ja, wenn 0.015 rauskommen sollte, das aber durch 0.01499999 approximiert wird, dann passt die Lösung mit +epsilon. Was aber wenn das Ergebnis der Rechnung 0.01499999 ist? Dann wird das Ergebnis verfälscht, weil auf 0.02 gerundet wird, obwohl 0.01 korrekt wäre.
Egal unter welchen Umständen man Gleitkommazahlen verwendet, es wird immer Probleme geben wenn man genaue Kommastellen braucht. Die einzige Lösung ist, einen für das Problem passenden Datentyp zu verwenden. (Siehe auch Furtbichlers Antwort)


Also ich habe noch keine Rechnung mit 0.01499999 gesehen. Ich mache das schon 25 Jahre und weiß wovon ich spreche. Man kann diesen Tipp annehmen oder auch nicht! Wenn man das nicht so macht, so kann ich Dir versprechend, das in bestimmten Branchen Dir die Software um die Ohren fliegt, wenn der Kunde anfängt nachzurechnen!

Natürlich ist die große Kunst nur an den richtigen Stellen zu runden, den gerundete Werte sind falsche Werte ;-)

JasonDX 27. Nov 2013 14:35

AW: kaufmännisch runden
 
Zitat:

Zitat von arnof (Beitrag 1237634)
Also ich habe noch keine Rechnung mit 0.01499999 gesehen. Ich mache das schon 25 Jahre und weiß wovon ich spreche.

Deswegen auch
Zitat:

Zitat von JasonDX (Beitrag 1237593)
man kann damit das Problem an einen anderen Ort verschieben, von dem man dann hofft, dass man dort nie vorbeikommt.

Du bist eben noch nie daran vorbeigekommen, und hoffst, dass dem so bleibt.

Zitat:

Zitat von arnof (Beitrag 1237634)
Wenn man das nicht so macht, so kann ich Dir versprechend, das in bestimmten Branchen Dir die Software um die Ohren fliegt, wenn der Kunde anfängt nachzurechnen!

Und was passiert, wenn der Kunde anfängt mit Rechnungen zu arbeiten, die 0.014999 als korrektes Ergebnis haben? Und wieso würde einem die Software um die Ohren fliegen, wenn sie korrekt rechnet? - also 0.015 rauskommt, wenn 0.015 rauskommen soll?
Ein +epsilon beim Runden eliminiert nicht die Ursache des Problems, sondern deckt nur die Symptome in den häufigsten Fällen ab.

Zitat:

Zitat von arnof (Beitrag 1237634)
Natürlich ist die große Kunst nur an den richtigen Stellen zu runden

Das auf jeden Fall.

arnof 27. Nov 2013 14:47

AW: kaufmännisch runden
 
@JasonDX: hat Du hier die Frage gestellt ?

Wenn Du einen Sinnvollen Beitrag hast, dann schreibe Ihn. Wenn Du meinst, das mein Beitrag falsch ist, dann hoffe ich für deine Kunden, das Du nichts mit WAWIS/ERP-System usw in der Entwicklung zu tun hast!

JasonDX 27. Nov 2013 15:03

AW: kaufmännisch runden
 
Zitat:

Zitat von arnof (Beitrag 1237650)
@JasonDX: hat Du hier die Frage gestellt ?

Wenn Du einen Sinnvollen Beitrag hast, dann schreibe Ihn.

Ich habe den Thread nicht begonnen, aber es haben sich im Verlauf Fragen für mich aufgetan, die die von dir vorgeschlagene Lösung betreffen. Die erste Frage war die: Was passiert, wenn einer der nicht vorgesehenen edge-cases auftritt? Die Frage baut auf der Beobachtung auf, dass der Lösungsvorschlag nicht alle Fälle korrekt behandelt.
Die zweite Frage im Beitrag war die was passiert, wenn eine Lösung verwendet wird, welche alle Fälle korrekt abdeckt. Ich bin noch keine 25 Jahre dabei, insofern ist es durchaus interessant zu wissen, wieso eine Lösung der anderen vorgezogen wird.

arnof 27. Nov 2013 15:33

AW: kaufmännisch runden
 
Jeder muss wissen wie er es löst, den Gedanken was dazuzurechnen ist erstmal ungewöhnlich und macht sicher auf den ersten Blick komisch und mag falsch erscheinen. Andere Datentypen zu nehmen ist sicher auch eine Lösung, ich möchte mich aber nicht nur auf EMBA verlassen, manchmal ist man da halt auch verlassen 8-)

Ich kann nur aus meiner Erfahrung sagen, da ich mich in meinen Programmiererleben sicher viele Monate damit beschäftigt habe.

Vor dem runden einfach 0.000000000001 oder sowas in der Art addieren, dann klapp es auch mit dem Runden auf 2 Stellen :thumb:

Billa 27. Nov 2013 16:05

AW: kaufmännisch runden
 
Hallo,

habe normalerweise nicht viel mit Fließkommaoperationen zu tun, aber vor Jahren einen Code aus der Computersteinzeit (COBOL) gesehen. Dort wurden für Beträge erstmal grundsätzlich nur ganze Zahlen gespeichert, also z.B. Beträge in Cent. Bei jeglicher Prozentrechnung oder Division wurde dem Ergebnis 0.5 hinzuaddiert und dann der Nachkommaanteil einfach abgeschnitten. Hat wohl zufriedenstellend funktioniert (stammte angeblich aus der Versicherungsbranche). Den Code habe ich leider nicht mehr, erinnere mich aber noch gut an diese seltsame Methode ... hth

Morphie 27. Nov 2013 18:49

AW: kaufmännisch runden
 
Weil es im weitesten Sinne zum Thema passt: http://javathreads.de/2009/03/niemal...ege-berechnen/

Mikkey 27. Nov 2013 18:52

AW: kaufmännisch runden
 
@billa:
Das von Dir beschriebene Verfahren ist nicht ungewöhnlich, in COBOL gibt es aber die Ergänzung "ROUNDED" für Multiplikationen, Divisionen und "Computations", die so etwas automatisch erledigen. Die Rundung nach ähnlicher Methode habe ich selbst in kaufmännischen Anwendungen selbst schon in C++ und in Assembler benutzt.

@arnof, JasonDX:
Rechnungen mit Fließkommazahlen sind nunmal ungenau und deshalb generell nicht für kaufmännische Zwecke geeignet. Das Addieren von einem noch so kleinen "epsilon" ist und bleibt ein Hack. Wenn einem kein "Dezimal"-Datentyp zur Verfügung steht, ist es besser, bei COBOL abzugucken und alle Rechnungen mit Ganzzahlarithmetik durchzuführen - die ist nämlich genau und man hat Rundungsvorgänge selbst in der Hand.

BUG 27. Nov 2013 19:47

AW: kaufmännisch runden
 
Wie man wo rundet, ist vermutlich auch anwendungsspezifisch.
Bei durch Menschen nachvollziehenden Rechnungen, kann ich mir gut vorstellen, dass das Runden nach jeder Operation (Zinsen berechnen) passiert und das Auf-/Abrunden durch Verträge geregelt ist.
Wenn ein komplexes Modell eine bestimmten Erwartungswert für die interne Verwendung ausspucken soll, wird vielleicht nur am Ende gerundet.

Das Runden durch Addieren von 5 auf der ersten nicht-signifikanten Stelle finde ich nicht so ungewöhnlich. Im Grunde realisiert man damit das normale Runden auf eine bestimmte Stelle ohne irgendwelche Sprünge.

arnof 27. Nov 2013 20:52

AW: kaufmännisch runden
 
Zitat:

Zitat von BUG (Beitrag 1237686)
Wie man wo rundet, ist vermutlich auch anwendungsspezifisch.
Bei durch Menschen nachvollziehenden Rechnungen, kann ich mir gut vorstellen, dass das Runden nach jeder Operation (Zinsen berechnen) passiert und das Auf-/Abrunden durch Verträge geregelt ist.
Wenn ein komplexes Modell eine bestimmten Erwartungswert für die interne Verwendung ausspucken soll, wird vielleicht nur am Ende gerundet.

Das Runden durch Addieren von 5 auf der ersten nicht-signifikanten Stelle finde ich nicht so ungewöhnlich. Im Grunde realisiert man damit das normale Runden auf eine bestimmte Stelle ohne irgendwelche Sprünge.

COBOL nein danke, gibt es das überhaupt noch in der normalen Welt?

Das Runden hat man selbst im griff, wenn man eine eigene Rundungfunktion generell benutzt, was ich immer mache.

Es gibt ja auch andere Länder in denen komplett anders zu Runden ist:Beispiel Schweiz, da ist die kleinste Einheit 5 Rappen :wink:

Uwe Raabe 27. Nov 2013 21:42

AW: kaufmännisch runden
 
Zitat:

Zitat von arnof (Beitrag 1237700)
COBOL nein danke, gibt es das überhaupt noch in der normalen Welt?

Bah! Da kann ich noch einen drauf geben. Aus dem IBM RPG II Reference Manual für System/36:

Zitat:

Half-adjusting is when the single digit to the right of the last decimal
position specified is added to the same position in the result field. All decimal positions
to the right of the position specified for that field are then dropped

laboca 30. Nov 2013 00:23

AW: kaufmännisch runden
 
Hallo,

irgendwie kehrt die Diskussion über Rundung immer wieder auf.
Hier muss man wohl unterscheiden was gerundet werden soll und nach welcher Regel.
Mathematisch, Kaufmännisch oder Banker's Rounding.
Und ob es ein positiver oder negativer Betrag ist.

Auch in der kaufmännischen Rundung spielt die 4 oder 5 Stelle nach dem Komma durchaus eine Rolle, wenn man mal Zinsdifferenzgeschäfte bei einer Bank betrachten würde. Im "Tante Emma" Laden eher weniger wenn's um "drei fünfundneunzig" geht...

Ganz gut im kaufmännischen Bereich bin ich mit folgender Funktion gefahren (hab ich mal aufgeschnappt oder zusammengestrickt oder wie auch immer.. ist lange her, daher kenne ich auch den Urheber nicht mehr der den Ansatz/Lösung gebaut hat, also nicht meine Federn...)

Code:
function RoundX( value: extended; const n: integer): extended;
var
  exp: extended;
  mode: TFPURoundingMode;
begin
  value := StrToFloat(FloatToStr(value));

  mode := GetRoundMode;
  exp := IntPower(10, n);
  if value > 0 then
  begin
    SetRoundMode(rmUp);
    result := trunc(value * exp + 0.5) / exp;
  end
  else
  begin
    SetRoundMode(rmDown);
    result := trunc(value * exp - 0.5) / exp;
  end;
  SetRoundMode(mode);
end;
HIH

Perlsau 4. Dez 2013 05:23

AW: kaufmännisch runden
 
Zitat:

Zitat von Smut (Beitrag 1238425)
Ganz tolles Thema, ganz tolle Beiträge, jedoch für mich als Anfänger total daneben...

Irgendwie finde ich es daneben, Antworten, die man mangels Grundkenntnissen nicht versteht, als total daneben zu bezeichnen ...

Zitat:

Zitat von Smut (Beitrag 1238425)
Frage: Was benutzt man am Besten an Formaten in der Datenbank für Preise und Mengen, um im Nachhinnein möglichst wenig Probleme zu haben?

Man verwendet für Geldbeträge gewöhnlich nicht denselben Typ wie für Mengen. Bei Geldbeträgen bietet sich der Currency-Typ (wie schon der Name nahelegt) an. Furtbichler hatte das in diesem Beitrag bereits ausführlich erläutert. Bei Mengen kommt es auf die jeweilige Einheit an: Für Stück genügt ein Integer, bei Gewichten, Längenmaßen und dergleichen nimmt man jenen Fließkomma-Typ, der die erforderliche Genauigkeit bereitstellt.

Deine Fragestellung ist mir etwas zu allgemein gehalten, denn als Anfänger mit nur lückenhaften Grundkenntnissen hat man eigentlich immer mit Problemen zu kämpfen. Da kommt man nicht drumrum, da muß man hindurch.

Zitat:

Zitat von Smut (Beitrag 1238425)
Ich habe obiges jetzt nicht so wirklich verstanden, und diese Art und Weise, dass ich irgend ein X dazuaddieren sollte, finde ich befremdlich. :oops:

Dann wäre es doch sicher nicht verkehrt, denjenigen, der dir das empfohlen hat, noch einmal um eine etwas einfacher formulierte Darstellung zu bitten. Ebenso hilfreich könnte es u.U. sein, dich selbst einmal mit den verschiedenen Float-Typen etwas ausgiebiger zu befassen.

Furtbichler 4. Dez 2013 06:59

AW: kaufmännisch runden
 
Zitat:

Zitat von Smut (Beitrag 1238425)
G...und diese Art und Weise, dass ich irgend ein X dazuaddieren sollte, finde ich befremdlich. :oops:

Vollkommen richtig. Das findet so ziemlich jeder.

Aaaber: In Delphi geht das kaum anders (bei Geld gibts -zum 1000x- den 'Currency' Datentyp, der mit einigen Datenbanken kompatibel is, sowit ich weiß)

Schau dir mal (aka bilde dich weiter ;-) ) Artikel über Floating Point, Fließkommazahlen usw. an. Das ist das gängige Format, indem Zahlen mit Dezimalanteil verarbeitet werden. Wieso gängig? Weil die Operationen darauf, also +,-,*,/, Sin etc. hochoptimiert durchgeführt werden können.

Pferdefuß: Damit können so "einfache" Zahlen wie "0,1" genaugenommen nicht dargestellt werden, dafür aber (z.B.) so wichtige Zahlen wie "0,09999999999643" und "0,100000000000367". Warum das so ist, wirst Du sehen, wenn Du die entsprechenden Artikel liest.

Beide Zahlen, also die 0,09999... und die 0,10000.. werden aber beim Debuggen in Delphi als 0,1 angezeigt (gemein, was?). Ein Vergleich mit "0,1" ergibt dann aber FALSE. Und ein Vergleich auf ">0,1" unter umständen auch. Und obwohl Delphi im Debugger die Zahl vielleicht als 0,1 anzeigt, wird sie in der Datenbank als 0,99999999999999643 abgelegt (oder eben als 0,1000000000000367).

Aber so etwas will man ja nicht unbedingt auf einer Rechnung sehen, oder als Preisschild im Supermarkt (die wären ganz schön lang, die Teile): Also muss man runden. Das muss man sowieso, wenn man prozentuale Anteile (Rabatt, VAT usw) ausrechnet. So, und beim Runden muss man dann erstens 0,005 dazuaddieren, damit man kaufmännisch rundet und dann blöderweise nochmals 0,0000000000001 um diesem Format ein Schnippchen zu schlagen.

Jeder Delphi-Programmierer geht da durch und stellt die gleichen Fragen. Und jeder gute Delphi-Programmierer weiß darauf irgendwann die Antwort. Ich gehe davon aus, das Du einer derjenigen sein wirst, die dem nächsten Rookie das ganz genau erklären kann.

Und für Leute, die erst Fahrrad fahren lernen ist es echt nervig, von den Fahrradfahrern, die an einem vorbeifahren, erklärt zu bekommen, wie leicht das doch ist.

p80286 4. Dez 2013 12:27

AW: kaufmännisch runden
 
Zitat:

Zitat von Smut (Beitrag 1238425)
Ich habe obiges jetzt nicht so wirklich verstanden, und diese Art und Weise, dass ich irgend ein X dazuaddieren sollte, finde ich befremdlich. :oops:

1,346+0,005=1,351 letzte Stelle streichen => 1,35
1,344+0,005=1,349 letzte Stelle streichen => 1,34

Was ist daran befremdlich? Du willst einen gerundeten Wert bekommen, der sieht Deinem ursprünglichen Wert nur ähnlich hat aber ansonsten garnichts mit diesem zu tun!
Das ist nur für die Darstellung.

Zitat:

Frage: Was benutzt man am Besten an Formaten in der Datenbank für Preise und Mengen, um im Nachhinnein möglichst wenig Probleme zu haben?
Das kommt darauf an! geht es um 12 Eier für dreifuffzigbenötigst du andere Typen als wenn du die Umsätze eines Großkonzerns zu verwalten hast.

Mein Tip dazu: wenn 16Bit reichen sollten, dann nimm 32Bit weil es kommt immer mehr als man glaubt.

Gruß
K-H

BUG 4. Dez 2013 15:55

AW: kaufmännisch runden
 
TheDailyWTF hat heute was zu dem Thema :mrgreen:

himitsu 4. Dez 2013 17:01

AW: kaufmännisch runden
 
Zitat:

Zitat von BUG (Beitrag 1238518)
TheDailyWTF hat heute was zu dem Thema :mrgreen:

Ist der Beitrag von einem Anti-Delphi-Jünger geschrieben wurden?

An allem ist Delphi schuld. :roll:

Man kann natürlich alles umständlich selber machen,
oder Delphi-Referenz durchsuchenSet8087CW or Delphi-Referenz durchsuchenSetRoundMode :angel:

p80286 4. Dez 2013 17:31

AW: kaufmännisch runden
 
Jetzt mal ernsthaft
gerundet werden soll auf 2 Stellen hinterm Komma, gegeben ist
0,44444444444444444444444445
was kommt raus? 0,45 oder 0,44?

Gruß
K-H

himitsu 4. Dez 2013 17:36

AW: kaufmännisch runden
 
0,44 ... egal ob mathematisch oder kaufmännisch gerundet


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