![]() |
kaufmännisch auf 0,5 oder 1 runden
Hallo zusammen,
ich versuche nun schon seit einiger Zeit ein bestimmtes Rundungsergebnis zu erreichen. Habe auch schon vieles hier gelesen und auch ausprobiert, aber ich konnte mein Problem damit leider noch nicht selbstständig lösen. :oops: Generell benötige ich eine Rundung, wo als Ergebnis immer nur eine Null oder eine 5 hinter dem Komma stehen soll; abhängig von dem Ergebnis der kaufmännischen Rundung. Quasi in 0,5er Einheiten kaufmännisch runden, anstelle der gewohnten 1er Einheiten. Beispiele: 12,2499 -> 12,0 12,25 -> 12,5 12,49 -> 12,5 12,5 -> 12,5 12,74 -> 12,5 12,75 -> 13,0 13,24454645 -> 13,0 Könnte mir hier jemand weiterhelfen? Vielen Dank schon mal im Voraus! |
Re: kaufmännisch auf 0,5 oder 1 runden
Die 12,50 ist ein Knackpunkt. Aber das hier auch ? :shock:
Zitat:
|
Re: kaufmännisch auf 0,5 oder 1 runden
Delphi-Quellcode:
müsste hinhaun ;)
round(x*2)/2
greetz Mike |
Re: kaufmännisch auf 0,5 oder 1 runden
@Hansa,
ja, so soll/ muss es sein sein :wink: @JasonDX, Round hatte ich hier bei meiner kaufmännischen Rundung auf Grund des Verhaltens (Bankers Rounding) gar nicht in Betracht gezogen. Dein Vorschlag funktioniert schon fast perfekt, vielen Dank! :thumb: Allerdings wird z.B. bei 12,25 auf 12 abgerundet, ich benötige allerdings genau ab 12,25 das Ergebnis -> 12,5, also eine Aufrundung. Als Workaround könnte ich 0.0000000001 vor dem Round hinzuzählen... Hat noch jemand einen Lösungsansatz? |
Re: kaufmännisch auf 0,5 oder 1 runden
Zitat:
sag mal, was und wie willste genau runden? nur kaufmännisch runden, ist das nicht... :pale: :pale: |
Re: kaufmännisch auf 0,5 oder 1 runden
@grenzgaenger,
du hast Recht, das richtige kaufmännische Runden ist es natürlich nicht. Ich möchte im Prinzip in 0,25er Schritten kaufmänisch runden, anstelle in 0,5er Schritten. Mein Anwendungsfall: Ermittlung von Urlaubsanspruch beim Arbeitsbeginn im lfd.Jahr. :wink: Es gibt u.a. die Regelung, dass der Urlaubsanspruch kaufmännisch auf halbe Tage gerundet wird. Wenn dann z.B. ein neuer Mitarbeiter am 15.Mai anfängt und er einen Ganzjahres-Urlaubsanspruch von 28 Tagen hat, so ergäbe das einen Urlaubsanspruch für dieses "angebrochene" Jahr von 17,672131147541 Tagen, "kaufmännisch" auf halbe Tage gerundet wären es dann 17,5 Tagen. Der Knackpunkt ist eben das kaufmännische Runden auf halbe Tage. |
Re: kaufmännisch auf 0,5 oder 1 runden
willst du jetzt in halbe schritte runden (x := trunc(x * 2) / 2) oder in 1/4 (x := trunc(x * 4) / 4)?
PS: ggf. kannst du noch 'n hundertstel dazu zählen... oder round hernehmen |
Re: kaufmännisch auf 0,5 oder 1 runden
Hi juergen!
Was hälst Du denn von einer simplen If-Abfrage?
Delphi-Quellcode:
Cheers,
function myround(z: real): real;
var r: real; begin r := frac(z); if (r >= 0.25) and (r < 0.75) then result := trunc(z) + 0.5 else if (r >= 0.75) then result := trunc(z) + 1 else result := trunc(z); end; Marc [edit] Funktion korrigiert [/edit] |
Re: kaufmännisch auf 0,5 oder 1 runden
Altes kaufm. Runden geht mit "Wert *50 /100" (wennch mich richtig erinner*g*)
|
Re: kaufmännisch auf 0,5 oder 1 runden
:-)
fast hat normal immer das selbe schema abschneiden(betrag * faktor) / faktor wenn aufgerundet werden soll, wird dann noch 'n kleiner betrag hinzugezählt, damit aufgerundet wird, bevor die die stellen abgeschnitten werden... also abschneiden(betrag * faktor + addon) / faktor bei einem hundertstel (zwei dezimalstellen), x = trunc(23,501 * 100 + 0.5) / 100 --> 2350,1 + 0.5 --> 2550,6 --> 2550 --> 25,50 auf diese weise durfte man immer in basic runden... ;-) bei rundung aufs fünferl, ist der faktor 20 ... :-) |
Re: kaufmännisch auf 0,5 oder 1 runden
Hallo zusammen,
im Moment verwende ich nachfolgendes, weil am genauesten: JasonDX's Vorschlag: round((StrToFloat(s) * 2 + 0.00000000000001)) / 2) Edit1.Text:= '12,4999999999999999999' -> 12,5 -> erst ab der 19.Stelle falsch Marc seine Funktion: myround(StrToFloat(Edit1.Text)) Edit1.Text:= '12,2499999999999999' -> 12,5 -> ab der 16.Stelle falsch grenzgaenger seine Funktion: trunc((StrToFloat(Edit1.Text)) * 2 + 0.5) / 2 Edit1.Text:= '12,4999999999999999' -> 12,5 -> ab der 16.Stelle falsch Prinzipiell lässt sich diese Ungenauigkeit mit diesem Konzept von Stringkonvertierung und Real wohl nicht lösen. Ich vermute man müsste expliziet nur mit Integer und dessen Funktionen arbeiten um genauere Ergebnisse zu erreichen. Da ich keine Summierungen verwende wo sich dann die evtl. Ungenauigkeiten summieren könnten, kann ich damit leben. Danke an alle für die Unterstützung! :thumb: |
Re: kaufmännisch auf 0,5 oder 1 runden
wenn du genaue ergebnisse haben möchtest, darfst du keine gleitkommazahlen (single, double, real, extented, float, etc. pp.) verwenden. hier kommen nur integer werte in betracht. also, z.b. integer, word, longint, int64, currency.
weshalb rechnest du die zahlen nicht erst in ein datenformat um, welches auch einigermassen valide ist? ansonsten hast du immer die probleme, dass sie in die eine oder andere richtung, willkürlich, kippen. damit wirst du nie glücklich werden... wenn du auf assembler ebene schaust, schau dir mal "binary coded decimal" (BCD) an. das format wurde extra erfunden um die rundungsprobleme zu vermeiden.. die CPU hat hierfür auch einen extra modus ... :-) (COBOL kann das von haus auf..., 'ne bilanz macht einfach keinen spass, wenn aktiva und passiva nicht aufgehen ;-) ) |
Re: kaufmännisch auf 0,5 oder 1 runden
Zitat:
|
Re: kaufmännisch auf 0,5 oder 1 runden
Zitat:
|
Re: kaufmännisch auf 0,5 oder 1 runden
Zitat:
|
Re: kaufmännisch auf 0,5 oder 1 runden
sehe grad, dass delphi einen eigenen BCD datentyp mit an board hat :-)
Delphi-Quellcode:
TBcd
|
Re: kaufmännisch auf 0,5 oder 1 runden
Zitat:
|
Re: kaufmännisch auf 0,5 oder 1 runden
@grenzgaenger
Jep, son Rechnungslegungsprogramm, was net richtig rundet, kommt net so gut beim Kunden.*fg* |
Re: kaufmännisch auf 0,5 oder 1 runden
Grundsätzlich würde ich das ursprüngliche Problem so lösen :
Delphi-Quellcode:
xr := trunc(x * 20 + 5) / 20
Dein Anwendungsfall muss aber IMHO anders gelöst werden! Laut Gesetz ... ![]() Absatz 2 : Bruchteile von Urlaubstagen, die mindestens einen halben Tag ergeben, sind auf volle Urlaubstage aufzurunden. ... werden also Werte von x,5 bis x,999999... auf x+1 aufgerundet ! Von kaufmännischem Runden ( schon gar nicht auf halbe Tage ) steht da nix. Man kann dem Arbeitnehmer natürlich mehr Urlaub geben als ihm eigentlich zusteht, wenn z.B. einen Anspruch von x,000000001 bis x,499999... auf x,5 aufgerundet würde:
Delphi-Quellcode:
Gesetzlich müsste man tatsächlich z.B. nur 0,1 Tage Urlaub gewähren *lol*
xr := trunc(x * 20 + 9) / 20
Übrigens: Dein Beispiel mit dem 15. Mai ergibt nur einen Urlaubsanspruch von 16,333... Tagen und nicht 17,672131147541 Tage , weil angebrochene Monate nicht zählen! |
Re: kaufmännisch auf 0,5 oder 1 runden
Liste der Anhänge anzeigen (Anzahl: 1)
@ bit4bit,
8) Für deine Beispiele hast du Recht. Da mein "Urlaubsrechner" aber nicht nur für Angestellte/ Beamte gelten soll, sondern vorwiegend im industriellen Bereich, musste ich alle möglichen Varianten abdecken... Zur Veranschaulichung habe ich das Programm mal angehängt. Ps.: Angewandtes Tarifrecht... Es ist erstaunlich wieviel Spielraum/ Interpretation Gesetzestext in der Praxis so zulässt. |
Re: kaufmännisch auf 0,5 oder 1 runden
Zitat:
solltest aber dennoch gucken, dass du deinen auftraggeber nicht, aufgrund eigenwilliger stundenrundung, verärgerst. auch wenn es zum vorteil gereicht, irgendjemand fühlt sich sicherlich auf die füsse getreten und macht stress. von daher, gilt der tip nach wie vor, lieber vorher runden, z.b. alles in dezimalminuten eingeben lassen oder in zeitminuten und sich das anschliessend bestätigen lassen. aufgrund der bestätigten daten, wird dann ohne rundung weitergerechnet. dann kann sich niemand beschweren, dass es anschliessend nicht passt :-) denke, die manuelle rundungsmethode (mit trunc...) habe ich vorhin genügend ausgeführt, so dass du auch die exotischsten rundungen problemlos hinbekommst. wenn deine zeit sekundengenau sein sollen, siehe dir doch mal das unix datetime format an... ansonsten kannst du ja problemlos 'n einges kreieren auf der basis deiner kleinsten zu berücksichtigten zeiteinheit... denke longint oder int64 sollten eigentlich reichen... sonst der currency typ :-) viel erfolg GG |
Re: kaufmännisch auf 0,5 oder 1 runden
Hallo grenzgaenger,
naja, die Aufgabenstellung war in diesem Fall eindeutig: - alles bezieht sich nur auf Tage. Ergebisse immer in ganze Tage oder halbe Tage (je nach Firma). Mein Problem war ja, die Personalsachbearbeiterin rechnet mit dem Taschenrechner nach und erhält ein ganz einfaches Ergebnis -> z.B. 12,25. Das soll dann auf 12,5 gerundet werden. Da wurde in meinem Fall durch die verwendeten Datentypen "falsch" gerechnet. Die jetzige Ungenauigkeit (16 Stellen hinter dem Komma) kann man aber in meienm Fall vernachlässigen, Ergebnis soll ja immer nur halbe oder ganze Tage sein. Es gibt bei einigen Firmen auch noch die Urlaubbsberechnungen in Stunden:Minuten (allerdings ziemlich selten). Hierfür hätte ich was in petto, weil ich mich schon mal ausführlich mit Stunden- und Minutenberechnungen auseinander gesetzt hatte. Dort verwende ich auschließlich Integer als Basis (2:30 Std = Integerwert von 150). Deine Erläuterungen zur Trunc-Funktion/Berechnung waren übrigens sehr gut! Gute Nacht! |
Re: kaufmännisch auf 0,5 oder 1 runden
So ist es allgemein:
Delphi-Quellcode:
In deinem Fall ist 'aGranularity' = 0.50.
Function RoundToGranularity(aValue, aGranularity: Double): Double;
Begin Result := Trunc(aValue / aGranularity + 0.5 + 1E-10) * aGranularity End; Die Ergebnisse sind zwar (weil Floating-Point) nicht genau, aber die Darstellungsfehler in der 15.ten Stelle sind irrelevant, weil Du ja formatiert ausgibst. Dafür kannst Du dann in Ruhe mit den Werten rechnen. Die Rundungsfehler schaukeln sich nur bei extremen Werten und/oder langen Iterationen langsam hoch. Wichtig ist hier die formatierte Ausgabe auf eine Nachkommastelle, aber das sollte man ohnehin machen. Zitat:
|
Re: kaufmännisch auf 0,5 oder 1 runden
Zitat:
und gesetzten gibt es keine 2 Firmen mit den selben Zeitmodellen....aber jede kommt und sagt: "Wie das muss man einstellen? Das ist doch Tarif standard!" (Von wegen....) Deswegen haben wir seit 12 Jahren einen Makrointerpreter und zig Makro Einsprungpunkte falls mal "ab und zu" jemand "seltsame" Regelungen umgesetzt braucht. @alzeimer: Wenn du zwei große Floats von einander abziehst kann schon im ersten Schritt ein echt interessantes Ergebnis bei rauskommen. |
Re: kaufmännisch auf 0,5 oder 1 runden
Zitat:
1. wo die Darstellungsfehler herkommen 2. was man überhaupt ausrechnet und 3. welche Genauigkeit man benötigt, dann kann man Floatingpointarithmetik bestimmungsgemäß und fehlerfrei verwenden. Wer die o.g. Punkte nicht richtig zu beantworten weiss, der muss zur Nachhilfe: Was interessieren mich Fehler in der 10 Stelle, wenn ich -im physikalischen Umfeld- nie mehr als 8 signifikante Stellen anzeigen muss (Ein Fehler von 0,00001%, das ist kleiner als fast jede Messeinrichtung). Im hier diskutierten Fall liegt die benötigte Genauigkeit bei genau einer Dezimalstelle bzw. 3-6 signifikanten Stellen. Und *das* schafft ein Double mit links, hier würde sogar ein Single ausreichen. Nicht verwechseln: Rundungsfehler und Darstellungsfehler. Ersteres kommt bei Computerrechnungen im Zahlenraum der reelen Zahlen doch öfter vor, letzteres ist eine Eigenheit der Floatingpoint-Datentypen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz