Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Fließkommazahlen auf Gleichheit prüfen (https://www.delphipraxis.net/80640-fliesskommazahlen-auf-gleichheit-pruefen.html)

Luckie 14. Nov 2006 12:23

Re: Fließkommazahlen auf Gleichheit prüfen
 
Zitat:

Zitat von Sourcemaker
ich habe gerade Deinen Artikel gelesen und mir fehlt die Erwähnung des Typs Currency,

Wie schon gesagt, ist das nur ein getarnter Integer. Somit fällt die Verwendung des Datentyps Currency unter den Tipp Ganzzahlen zu verwenden. Zudem ist die Genauigkeit so gering, dass sich mathematische Berechnung, die eine höhere Genauigkeit erfordern, damit nicht durchführen lassen.

stoxx 1. Mai 2009 19:14

Re: Fließkommazahlen auf Gleichheit prüfen
 
Zitat:

Dafür ist Currency eben 100% genau. Bei Addition und Subtraktion. Und da sind 0.1 Euro - 0.1 Euro garantiert = 0,0000!

....

Wie schon gesagt, ist das nur ein getarnter Integer. Somit fällt die Verwendung des Datentyps Currency unter den Tipp Ganzzahlen zu verwenden.

ich glaube, ihr täuscht Euch da gewaltig. Currency ist nur vom Typ Extended.
Vielleicht mit 8 Byte etwas ganauer als Double, ja .. aber immer noch ungenau .. folgendes Beispiel demonstriert es ...




Delphi-Quellcode:
var
 cStart, c1, cadd : Currency;

begin



cStart := 10000000000000;
cadd := 0.1;
c1 := cStart;

for i := 1 to 10 do begin
     c1 := c1 + eAdd;

end; // for i


if          c1 = 10000000000001 then
        ShowMessage('Gleich = ');


if SameValue(c1, 10000000000001) then
        ShowMessage('Gleich SameValue ');

man sieht auch, wenn man z.b. rechnet:

c1 := c1 + cAdd;


und ins CPU Fenster geht, dass dort steht:

uFrm_Main_XM.pas.1201: cas c1 := c1 + eAdd;
008BFEC1 DBAD90FEFFFF fld tbyte ptr [ebp-$00000170]
008BFEC7 D80DBC0D8C00 fmul dword ptr [$008c0dbc]
008BFECD DFAD28FFFFFF fild qword ptr [ebp-$000000d8]
008BFED3 DEC1 faddp st(1)
008BFED5 DFBD28FFFFFF fistp qword ptr [ebp-$000000d8]




ich kenn mich zwar in Assembler nicht wirklich gut aus, aber "faddp" sind definitiv Fließkommezahlen



..

himitsu 1. Mai 2009 22:29

Re: Fließkommazahlen auf Gleichheit prüfen
 
Currency ist ein skalierter Int64, nur das er über die FPU berechnet wird.

Delphi-Quellcode:
Procedure TForm2.Button1Click(Sender: TObject);
  Var C: Currency;
    i: Int64 absolute C;
    i2: Integer;

  Begin
    For i2 := 0 to 100 do Begin
      C := i2 * 0.0531;
      Label1.Caption := CurrToStr(C);
      Label2.Caption := FloatToStr(i / 10000) + '   ' + IntToStr(i2);
      Application.ProcessMessages;
      Sleep(250);
    End;
  End;

stoxx 2. Mai 2009 00:37

Re: Fließkommazahlen auf Gleichheit prüfen
 
Zitat:

Zitat von himitsu
Currency ist ein skalierter Int64, nur das er über die FPU berechnet wird.


hmmm ... warum rechnet er dannn mein Beispiel von oben nicht richtig?

himitsu 2. Mai 2009 10:10

Re: Fließkommazahlen auf Gleichheit prüfen
 
also bei mir sieht es so aus ... k.A. wo bei dir das fmul her kommt :gruebel:
Delphi-Quellcode:
asm
  // c1 := c1 + cAdd;
  fild qword ptr [&c1]
  fild qword ptr [&cAdd]
  faddp st(1)
  fistp qword ptr [&c1]
  wait

  // if c1 = Extended(10000000000001) then
  fld tbyte ptr [10000000000001]
  fild qurd ptr [&c1]
  fcompp
  fstsw ax
  sahf
  jnz ...
end;
vielleicht fällt dir das fi... bzw. f.. auf > i für Integer

ein Problem seh ich nur beim Vergleich ... wo Delphi aus dem 10000000000001 einen Extended macht ... typlose Umwandlungen wesehn nur in Integertypen und Extended (nach Currency wandelt Delphi keine Konstanten von alleine um)

Dipl Phys Ernst Winter 2. Mai 2009 19:11

Re: Fließkommazahlen auf Gleichheit prüfen
 
Zitat:

Ich bräuchte aber ein entsprechende Beispiel, beim dem die Abfrage auf Gleichheit nicht funktioniert
Bitt sehr:
Delphi-Quellcode:
var
  a, b: extended
begin
  a:= 0.9;
  b:= 0.09;
  if 0.1*a=b then lblIstGleich.Caption:= 'ist gleich'
             else lblIstGleich.Caption:= 'ist ungleich';
end;

Korrekt treibt man beim Vergleich von Gleitkommazahlen Epsilontik:

const
  eps= 1e-14;              // Definiert eine Umgebung für Rundungsfehler
var
  a, b: extended;
begin
  if a<-eps then....       // a<0
  if Abs(a)<eps then...    // a=0 
  if a>eps then...         // a>0
  if Abs(a-b)<eps then     // a=b
[edit=mkinzler]Delphi-Tag eingefügt Mfg, mkinzler[/edit]

stoxx 3. Mai 2009 13:35

Re: Fließkommazahlen auf Gleichheit prüfen
 
edit
War ein Denkfehler, ich glaub, jetzt hab ichs verstanden :-)
der Wert steht zwar drin, kann aber wiederum nur mit einer anderen Currency verglichen werden, weil wie Himitsu schon sagte, der Vergleich schief geht.

Delphi-Quellcode:
var

 cStart, c1, c2, c3, c4, cmax, cadd : Currency;

 iAbsolute : Int64  absolute c1;

begin



cStart := 10000000000000;
cadd := 0.1;
c1 := cStart;

for i := 1 to 10 do begin
     c1 := c1 + cAdd;
end; // for i

ShowMessage(IntToStr(iAbsolute)); // <- hier erscheint: 100000000000010000 (korrekt)

if          c1 = 10000000000001 then
        ShowMessage('Gleich = ');

stoxx 3. Mai 2009 14:00

Re: Fließkommazahlen auf Gleichheit prüfen
 
Zitat:

Zitat von himitsu
also bei mir sieht es so aus ... k.A. wo bei dir das fmul her kommt :gruebel:


Ich glaube, das war mein Fehler *duck* .. wenn man in das Quelltextbeispiel guckt, dann steht dort "eAdd" und nicht "cAdd" wie geplant .. eAdd war aber dummerweise ein Extended .. und das fmul ist die Multiplikation mit dem Skalierungsfaktor bei Currency (10000)
sowas blödes .. :freak:
ich nehm alles zurück, was ich zu Currency gesagt habe :-) :wall:

himitsu 3. Mai 2009 14:04

Re: Fließkommazahlen auf Gleichheit prüfen
 
Zitat:

Zitat von stoxx
ich nehm alles zurück, was ich zu Currency gesagt habe :-) :wall:

:angel:


und drum hatte ich im anderem Thread auch 'ne reine Integerversion gepostet, da die FPU bzw. die Floattypen halt einiges an Ungenauigkeit mit sich bringt.


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

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