Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Problem mit RoundTo((100*0.01),0) (https://www.delphipraxis.net/112284-problem-mit-roundto-100%2A0-01-0-a.html)

zecke 18. Apr 2008 01:15


Problem mit RoundTo((100*0.01),0)
 
:hi:

Nach sehr langer Zeit habe ich mal wieder ein Problem. Mir fällt einfach kein Fehler auf.

Ich möchte Zahlen im Grunde einfach immer abrunden (ohne Nachkommastellen). Das mache ich mit RoundTo und RoundMode habe ich auf truncate.

Erstmal der Code:

Delphi-Quellcode:
   p7:=RoundTo((staedte*0.01),0);
   showmessage(floattostr(staedte));
   showmessage(floattostr(RoundTo((100*0.01),0)));
   showmessage(floattostr(p7));
staedte ist vom Typ Real, ebenso wie p7. Außerdem hat staedte den Wert 100.

showmessage Nummer 1 zeigt mir korrekter Weise "100" an. showmessage Nummer 2 zeigt mir korrekter Weise "1" an. showmessage Nummer 3 zeigt mir "0" an. :wiejetzt: (Die 5000 showmessage Befehle sind übrigens nur zu Demonstrationszwecken vorhanden ;))

Was mache ich denn hier falsch? In der Hilfe habe ich bereits geforscht, auch die Forensuche half mir nicht weiter. Hoffe ich habe keinen Thread übersehen und ihr könnt mir einen Tipp geben. Habe übrigens auch schon die anderen RoundModes ausprobiert, lediglich Up macht es richtig, logisch, aber das will ich ja nicht, falls staedte eine andere Zahl ist.

peschai 18. Apr 2008 05:36

Re: Problem mit RoundTo((100*0.01),0)
 
Hallo
Also ich bin verblüfft! Ich kann das Problem unter Delphi2007Prof nachstellen!
-> Das zweite Showmessage zeigt ein anderes Ergebnis, was nicht sein darf!
Zuerst dachte ich, daß dies ein Problem von REAL sei, aber selbst die Umstellung auf DOUBLE zeigt hier unterschiedliche Werte an!
Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
var
  p7 : double;
  staedte : double;
begin
  p7 := 0.0;
  staedte := 100.0;

  SetRoundMode(rmTruncate);

  p7:=RoundTo((100.0*0.01),0); showmessage(floattostr(p7));
  p7:=RoundTo((Staedte*0.01),0); showmessage(floattostr(p7)); // hier anderes ergebnis!
end;

peschai 18. Apr 2008 05:45

Re: Problem mit RoundTo((100*0.01),0)
 
Hallo
Noch ein Ergänzung:
Ein Änderung des Potenzparameters von "0" auf "-1" bringt ebensfalls unterschiedliche Ergebnisse "1" und "0,9"!
Delphi-Quellcode:
  // Staedte, p7 : double; // RoundTo(Double,...)
  SetRoundMode(rmTruncate);
  Staedte := 100.0;
  p7:=RoundTo((100.0*0.01),-1); showmessage(floattostr(p7));
  p7:=RoundTo((Staedte*0.01),-1); showmessage(floattostr(p7));
War so frei und habe bei CodeGear einen BugReport eröffnet, nachdem ich dort in der IssueSuche nichts mit RoundTo gefunden habe.
Zitat:

Report From: Delphi-BCB/Compiler/Delphi Report #: 61093

peschai 18. Apr 2008 06:25

Re: Problem mit RoundTo((100*0.01),0)
 
Hallo,
Dieser Delphi Fehler hat mir keine Ruhe gelassen, aber hier ein ein Workaround:
Habe die original Funktion aus "math" mit extended redefiniert und damit scheint es jetzt zu funktionieren...
Delphi-Quellcode:
function MyRoundTo(const AValue: Extended; const ADigit: TRoundToRange): Extended;
var
  LFactor: Extended;
begin
  LFactor := IntPower(10, ADigit);
  Result := Round(AValue / LFactor) * LFactor;
end;
Das Problem scheint zu sein, daß math.RoundTo mit Double definiert ist, intern aber das System.Round verwendet wird, was aber mit Extended definiert ist. Delphi scheint hier ein Problem zu haben mit der Übergabe der "intern konvertierten werte" an die Round funktion ....

mkinzler 18. Apr 2008 06:35

Re: Problem mit RoundTo((100*0.01),0)
 
Komsich, das dieser Fehler vorher noch niemand aufgefallen zu sein scheint. :gruebel:

peschai 18. Apr 2008 07:08

Re: Problem mit RoundTo((100*0.01),0)
 
@mkienzler
du hast recht, das hat mich auch gewundert. Könnte aber daran liegen daß "SetRoundMode(rmTruncate);" wohl eher selten benutzt wird. Mit der standard Einstellung scheint das problem nicht sichtbar zun werden...

Ich sehe hier ein großes Risiko, daß eventuell alle Funktionen mit Double die intern eine Extended-Funktion aufrufen damit in besonderen fällen (selten?) betroffen sein könnten... Am Liebsten sollten alle diese mit extended redefiniert werden ....

mkinzler 18. Apr 2008 07:20

Re: Problem mit RoundTo((100*0.01),0)
 
Ich verwende eigentlich fast immer Extended, das werden viele andere vielleicht auch machen.

DelphiKlaus 18. Apr 2008 07:32

Re: Problem mit RoundTo((100*0.01),0)
 
Hallo,

liegt das nicht vielleicht einfach daran, dass z.B. 100 * 0.01 nicht unbedingt 1 ergibt, sondern vielleicht 0.99999999.

angos 18. Apr 2008 07:35

Re: Problem mit RoundTo((100*0.01),0)
 
das problem wird eher sein, dass wenn man einer Real-Variable den Wert 100 zuweist, diese einen tatsächlichen Wert von 99,9999999999999999 hat ;) da es ja nicht auftritt, wenn die gesamte berechnung direkt durchgeführt wird.
aber ansich habe ich die gleiche Vermutung wie du... das ist halt einfach der Grund, Fließkommazahlen zu vermeiden wunderbar dargestellt an einem praktischen Beispiel

Gruß

peschai 18. Apr 2008 09:13

Re: Problem mit RoundTo((100*0.01),0)
 
@DelphiKlaus&Angos
Natürlich habt ihr hier recht, das digitale Speichern von Gleitkommazahlen hat dieses Problem grundsätzlich.
Das Verhalten hier ist aber, daß trotz identischen Typen (alles Double) hier ein unterscheidliches Verhalten/Ergebnis auftritt.
Ich hätte weniger ein Problem wenn dieser DigitaleFehler identisch aufgetreten wäre.
Codegear muss hier ein identisches Verhalten sicherstellen!
Delphi-Quellcode:
// Staedte, p7 : double; // RoundTo(Double,...)
SetRoundMode(rmTruncate);
Staedte := 100.0;
p7:=RoundTo((100.0*0.01),-1); showmessage(floattostr(p7));
p7:=RoundTo((Staedte*0.01),-1); showmessage(floattostr(p7));


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:43 Uhr.
Seite 1 von 3  1 23      

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