![]() |
AW: Unterschiedliche Ergebnisse beim Runden
Zitat:
Alle drei sind mathematisch korrekte Rundungsmethoden. kaufmännische Rundung: Alles incl. 0.5 wird aufgerundet. technische Rundung: 0.5 und darunter wird abgerundet. mathematische Rundung (bankers rounding): .00 bis .49 wird abgerundet .60 bis .99 wird aufgerundet .51 bis .59 wird aufgerundet .50 wird derart gehandelt,das die beizubehaltende Zahl zur nächsten geraden Zahl gerundet wird. Bsp dafür: 2.25 wird zu 2.2 2.35 wird zu 2.4 Letzteres ist bereits auf Prozessor-Ebene so implementiert (zumindest bei x86) und wird standardmäßig von den entsprechenden Sprachen incl(Delphi....schon seit Turbo Pascal-Zeiten) so für Rundungen verwendet. ![]() [/KLUGSCHEISSMODUS OFF] und hier mal meine Routine für alle drei Methoden:
Delphi-Quellcode:
TYPE
TRoundMethod = (rmKfm,rmTec,rmMat); function RoundDirect(zahl:extended;dezimalstellen:Byte;methode:TRoundMethod=rmKfm):extended; var hlp,hlp2,di : Extended; begin di := Power(10,dezimalstellen); hlp := trunc(zahl*di); hlp2 := (zahl*di)-hlp; case methode of rmKfm : if (hlp2 >= 0.5) then hlp := hlp+1; rmTec : if (hlp2 > 0.5) then hlp := hlp+1; rmMat: begin if (hlp2 > 0.5) then hlp := hlp+1 else begin if (odd(trunc(hlp))) then hlp := hlp +1; end; end; end; result := hlp/di; end; |
AW: Unterschiedliche Ergebnisse beim Runden
Zitat:
|
AW: Unterschiedliche Ergebnisse beim Runden
Zitat:
Die Wahl des Rundungsverfahrens hängt doch von der Anwendung ab. Wenn der Schlüssel ins Schloss passen soll, ist es günstiger bei der Berechnung abzurunden, damit es am Ende nicht klemmt. |
AW: Unterschiedliche Ergebnisse beim Runden
Zitat:
Die andere Form der Rundung spielt insbesondere bei Statistiken eine Rolle, da dadurch die die Ergebnisse weniger verfälscht werden. Daher wird es auch verzerrungsfreie Rundung genannt. Ich glaube dass es auch bei der Vermessung und Navigation eine Rolle spielt, aber das ist schon so lange her, dass ich mir nicht mehr ganz sicher bin. Der Einsatz ist daher eher im mathematisch-technischen Bereich zu finden. |
AW: Unterschiedliche Ergebnisse beim Runden
Belassen wir es dabei. Wenn ich es mal brauche, kann ich mich ja noch mal informieren. :roll:
|
AW: Unterschiedliche Ergebnisse beim Runden
..."ist ja mathematisch falsch. Wie kommen die auf die Regel zur nächsten geraden Zahl zu runden?"...
also wir habe das Runden von ".5" per "GeradZahlRegel" schon in der Schule in Mathematik so gelernt und dann überall in Physik, Chemie, E-Technik uws. angewannt. Bei uns nannte man die ersten 10Jahre die Schule "POS" ala "Polytechnische-Oberschule", und zumindest Mathematik und Naturwissenschaften wurden da garnicht so schlecht und sogar fast politikfrei gelehrt. Mathematisch und vor allem statistisch dient die "GeradZahlRegel" der Gleichverteilung der Rundungsfehler, was sich problemlos beweisen lässt. Aber da es nunmal so ist, das es heute teils von Bundesland zu Bundesland und Schulart zu Schulart verschiedene Lehrstandards gibt und die Diskussion darüber müßig ist, haben wir unsere Software zentral einstellbar gemacht, da kann der Chef es sich so festlegen, das es so ist wie er es gelernt hat und/oder es für richtig hält:) Das Grundsatzproblem der nunmal FPU und letztendlich doch binär basierten Fließkommatypen kommt ja immer noch dazu, und sollte VOR DEM RUNDEN beachtet werden... also erst mal die "gewollte Zahl" REKONSTRUIEREN, dann das Ergebnis wie es so schön heißt auf nötige und sinnvolle Genauigkeit RUNDEN. Wen all das eigentlich garnicht interessiert, der nehme einfach "integer:=Round(double);" und es wird zu 99% etwas sinvolles heraus kommen. |
AW: Unterschiedliche Ergebnisse beim Runden
Hallo Richard,
Es ist ja schön, dass du dein Problem gelöst hast, wie in #20 gezeigt, aber es wäre doch noch etwas schöner, wenn auch geklärt worden wäre, was eigentlich das Problem war. Leider hast du auf die direkte Frage in #4 "Welche Typen haben Zahl und Multi?" nicht geantwortet. In den Screenshots konnte man sehen, dass Multi den Wert 10 und Zahl den Wert 0.075 hatte, wobei interessant gewesen wäre, wie der Wert 0.075 entstanden war. In den vielen Themen wurde leider meist an deinem Problem vorbei geredet, denn mit den unterschiedlichen Methoden des Rundens hatte das nichts zu tun. Das Problem ist, dass Zahlen, die in dezimaler Schreibweise exakt dargestellt werden können, in binärer Schreibweise nicht exakt darstellbar sind. Ich hab mal geprüft, wie die Werte X=0.075 und 10*X in der FPU aussehen, wenn vorher X unterschiedliche Typen hat. In der nachstehenden Tabelle seht ihr jeweils den Typ von X, den Wert in der FPU in dezimaler Darstellung mit 20 Nachkommstellen und den Speicherauszug des Wertes in der FPU.
Code:
Man sieht sehr schön, dass wenn 0.075 in einem Double gespeichert war, in der FPU daraus ein Wert wird, der geringfügig kleiner ist.
CPU interne Darstellung von X=0.075, wobei X den jeweils angegebenen Typ hat:
Single 0.07500000298023223880 00 00 00 00 00 9A 99 99 FB 3F Real48 0.07500000000004547470 00 00 00 9A 99 99 99 99 FB 3F Double 0.07499999999999999720 00 98 99 99 99 99 99 99 FB 3F Extended 0.07500000000000000000 9A 99 99 99 99 99 99 99 FB 3F CPU interne Darstellung von 10 * X=0.075, wobei X den jeweils angegebenen Typ hat: Single 0.75000002980232238800 00 00 00 00 80 00 00 C0 FE 3F Real48 0.75000000000045474700 00 00 80 00 00 00 00 C0 FE 3F Double 0.74999999999999997200 00 FE FF FF FF FF FF BF FE 3F Extended 0.75000000000000000000 00 00 00 00 00 00 00 C0 FE 3F Das Gleiche passiert auch bei dem mit 10 multiplizierten Wert, der dann, auf 7 gerundet wird, und zwar unabhängig davon, welche Methode der Rundung verwendet wird. Die Tabelle wurde mit der nachstehenden Routine erstellt:
Delphi-Quellcode:
PROCEDURE TestRounding;
type TTBA=Array[0..9] of Byte; PROCEDURE Store(Value:Extended; Typ:String; var S:String); var I:Integer; T:String; begin Str(Value:0:20,T); S:=S+#13#10+Typ+' '+T+' '; for I:=0 to 9 do S:=S+' '+IntToHex(TTBA(Value)[I],2); end; const H1='CPU interne Darstellung von X=0.075, wobei X den jeweils angegebenen Typ hat:'; H2='CPU interne Darstellung von 10 * X=0.075, wobei X den jeweils angegebenen Typ hat:'; ZahlS:Single=0.075; ZahlR:Real48=0.075; ZahlD:Double=0.075; ZahlE:Extended=0.075; var I:Integer; S:String; begin S:=H1; Store(ZahlS,'Single ',S); Store(ZahlR,'Real48 ',S); Store(ZahlD,'Double ',S); Store(ZahlE,'Extended',S); S:=S+#13#10#13#10+H2; Store(10*ZahlS,'Single ',S); Store(10*ZahlR,'Real48 ',S); Store(10*ZahlD,'Double ',S); Store(10*ZahlE,'Extended',S); Clipboard.AsText:=S; end; |
AW: Unterschiedliche Ergebnisse beim Runden
Zitat:
Ansonsten hast du natürlich recht mit der internen Darstellung. Das folgende Beispielprogramm demonstriert das (zumindest unter Win32):
Delphi-Quellcode:
Es lässt sich aber auch zeigen, daß die Verwendung der von mir vorgeschlagenen Unit das Problem löst:
program Project262;
{$APPTYPE CONSOLE} var MultiS: Single; WertS: Single; MultiD: Double; WertD: Double; begin MultiS := 100; MultiD := 100; WertS := 0.075; WertD := 0.075; Writeln('Single: ', Round(MultiS * WertS)); Writeln('Double: ', Round(MultiD * WertD)); Readln; end.
Delphi-Quellcode:
program Project263;
{$APPTYPE CONSOLE} uses DecimalRounding_JH1; var MultiS: Single; WertS: Single; MultiD: Double; WertD: Double; begin MultiS := 100; MultiD := 100; WertS := 0.075; WertD := 0.075; Writeln('Single: ', Round(MultiS * WertS)); Writeln('Double: ', Round(MultiD * WertD)); Writeln('Single JH: ', DecimalRoundSgl(MultiS * WertS, 0)); Writeln('Double JH: ', DecimalRoundDbl(MultiD * WertD, 0)); Readln; end. |
AW: Unterschiedliche Ergebnisse beim Runden
@Uwe,
Oh, das ist mir jetzt aber peinlich. Na klar war Multi=100 gesetzt. Ich hab noch mal die Tabelle auf Basis Multi=100 erstellt. CPU interne Darstellung von X=0.075, wobei X den jeweils angegebenen Typ hat: Single 0.07500000298023223880 00 00 00 00 00 9A 99 99 FB 3F Real48 0.07500000000004547470 00 00 00 9A 99 99 99 99 FB 3F Double 0.07499999999999999720 00 98 99 99 99 99 99 99 FB 3F Extended 0.07500000000000000000 9A 99 99 99 99 99 99 99 FB 3F CPU interne Darstellung von 100 * X=0.075, wobei X den jeweils angegebenen Typ hat: Single 7.50000029802322388000 00 00 00 00 A0 00 00 F0 01 40 Real48 7.50000000000454747000 00 00 A0 00 00 00 00 F0 01 40 Double 7.49999999999999972000 80 FD FF FF FF FF FF EF 01 40 Extended 7.50000000000000000000 01 00 00 00 00 00 00 F0 01 40 |
AW: Unterschiedliche Ergebnisse beim Runden
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:05 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 by Thomas Breitkreuz