![]() |
Runden liefert falsches Ergebnis
Hi@all!
Ich habe mir mal den spass gemacht und eine eigene Rundungsfunktion geschrieben. Es geht hier um das Prinzip, ich möchte also verstehen, warum ich falsche Ergebnisse bekomme und nicht hören, dass Delphi ja eine interne Rundungsfunktion hat ;-) :
Delphi-Quellcode:
Zum Fehler:function roundexact(X:extended;digits:integer):extended; var intzahl:integer; intzahl2:integer; begin intzahl:=trunc(x*power(10,digits+1)); intzahl2:=trunc(x*power(10,digits))*10; if intzahl-intzahl2 < 5 then result:=intzahl2/power(10,digits+1) else result:=int(intzahl2/10+1)/power(10,digits); end; An und für sich funktioniert diese Funktion super. Ich glaube auch nicht, dass der Fehler direkt an dem Funktionsaufbau liegt, sondern daran, wie Delphi intern Single zu Extended etc konvertiert: Ich habe folgende Berechnung, die am Schluss gerundet werden soll:
Code:
Das Ergebnis ist, wie jeder noch leicht selber ausrechnen können sollte: 290.325
3675*(14/200+0.009)
Demzufolge müsste unsere Rundungsfunktion als Ergebnis 290.33 liefern, richtig? Dies tut sie auch, wenn ich sie mit folgendem Befehl starte:
Delphi-Quellcode:
Wenn ich aber schreibe:
showmessage(floattostr(roundexact(290.325,2))); //Messagebox zeigt wie erwartet 290.33 an
Delphi-Quellcode:
erhalte ich als ergebnis 290.32
showmessage(floattostr(roundexact(3675*(14/200+0.009),2))); //Messagebox zeigt 290.32 an ?!?!
Kann mir das jemand erklären?? Ich habe mal ein bisschen mit dem Debugger rumgespielt: Wenn das Ergebnis falsch berechnet wird, liefert
Delphi-Quellcode:
das Ergebnis 290324 anstatt von 290325
intzahl:=trunc(x*power(10,digits+1));
WARUM??? :wall: :wall: :wall: :wall: :wall: Viele Grüße, Michael [edit] Mit X als Single-precision funktionierts! Warum? Ist da ein Delphi-interner Fehler bei der Umwandlung von Single->Extended oder hat das generell irgendwas mit der Darstellbarkeit von Zahlen in Computer zu tun? -> Schätze Delphi wandelt das Ergebnis bei der Parameterübergabe in 290.324999999999999999 um oder so?[/edit] [edit2] Dafür gehts dann mit anderen Zahlen nicht mehr...z.B. 4650*0.0995=462.675 ... woran liegt das??? [/edit2] |
Re: Runden liefert falsches Ergebnis
Gebrochene Fließkommazahlen lassen sich mit verschiedenen Exponenten darstellen.
Je nach vorherigen Operationen und Exponent treten Ungenauigkeiten auf. Statt 290,325 kann die Variable intern auch z.B. 290,324999999998 enthalten. Bei der Umwandlung in einen String wird das natürlich ausgeglichen und die Anzeige stimmt. Ein direkter Vergleich würde aber Ungleichheit feststellen. Trunc(2903224,999999998) ergibt 2903224. |
Re: Runden liefert falsches Ergebnis
Zitat:
|
Re: Runden liefert falsches Ergebnis
Zitat:
Ich meine im Endeffekt kommt es auf's Selbe raus, weil 16 ja auch eine 2er Potenz ist, aber es geht mir jetzt eher ums Prinzip. |
Re: Runden liefert falsches Ergebnis
Eine Sache zu verstehen ist eine Sache, für andere verständlich zu formulieren schon schwieriger...
Schau mal ![]() |
Re: Runden liefert falsches Ergebnis
Und was kann ich dagegen tun? Weiß jemand, wie die Umwandlung in nen String dieses Problem "umgeht" und dort exakt anzeigt?
|
Re: Runden liefert falsches Ergebnis
Berücksichtige die Schutzstellen, addiere also vor dem "Trunc" 0.5 dazu.
|
Re: Runden liefert falsches Ergebnis
Okay, ich habs jetzt umgebaut zu:
Delphi-Quellcode:
Müsste ich aber nicht eigentlich 0.50001 dazuaddieren oder sowas?
function roundexact(X:single;digits:integer):single;
begin result:=x*power(10,digits)+0.5; result:=trunc(result); result:=result/power(10,digits); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:01 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