Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   DUnit und Fließkommazahlen Problem (https://www.delphipraxis.net/211503-dunit-und-fliesskommazahlen-problem.html)

TurboMagic 25. Sep 2022 10:14

DUnit und Fließkommazahlen Problem
 
Hallo,

für eine DUnit Demo schreibe ich gerade einen einfachen Taschenrechner und
laufe jetzt aber bei den unit Tests in Fließkomma Probleme.

Der Taschenrechner hat 2 Operanden 1 und 2, die jeweils ein Double sind.
Ich schriebe einen DUnit Tests mit dem Inhalt:

Delphi-Quellcode:
procedure TestTCalculatorLogic.TestSetOperand1Positive;
begin
  FCalculatorLogic.Operand1 := 4.6;
  CheckEquals(4.6, FCalculatorLogic.Operand1);
end;
Der Test schlägt fehl mit der Meldung, dass 4.6 erwartet würde und der Wert von Operand1 4.6 wäre :?
Ja ich weiß, FLießkommazahlen sind nicht unendlich präzise und DUnit's CheckEquals nutzt Extended
als Übergabeparameter, aber sollte das nicht für eine Nachkommastelle trotzdem funktionieren?
Und sollte nicht die Fehlermeldung, falls es wirklich irgendwo weiter hinten bei den Nachkommastellen
dadurch Differenzen gibt, die genaue Zahl im Text nennen?

Was sind meine Möglichkeiten diese Demo umzubauen. so dass ich nicht in diese Probleme laufe?
Umstellen von Double auf Currency, damit hat man zwar nur 4 Nachkommastellen, aber keine Präszisions-
probleme dieser Art?

Grüße
TurboMagic

Amateurprofi 25. Sep 2022 11:32

AW: DUnit und Fließkommazahlen Problem
 
Zitat:

aber sollte das nicht für eine Nachkommastelle trotzdem funktionieren?
Du machst da einen Denkfehler.
4.6 hat, dezimal ausgedrückt, zwar nur eine Nachkommastelle, binär ausgedrückt aber "unendlich" viele Nachkommastellen.
Wie sieht denn die Funktion CheckEquals aus?
Vorschlag: Benutze die Funktion SameValue aus System.Math.

Delphi-Quellcode:
var V:Double; Res:Boolean;
begin
   V:=4.6;
   Res:=SameValue(4.6,V); // Res ist True
end;

himitsu 25. Sep 2022 11:52

AW: DUnit und Fließkommazahlen Problem
 
CheckEquals nutzt intern kein SameValue, sondern vergleicht selber
Delphi-Quellcode:
       (abs(expected-actual) > delta) then


Es gibt ein CheckEquals mit Delta-Parameter ... benutze das und verwende z.B. die Konstante ExtendedResolution, DoubleResolution, SingleResolution oder was Eigenes, wie 0.0000001.
Delphi-Quellcode:
 CheckEquals(4.6, FCalculatorLogic.Operand1, SingleResolution);


Genauso, wie bei SameValue, kommt als Default-Parameter eine 0 rein,
aber SameValue nutzt bei 0 nicht wirklich 0, sondern z.B. ExtendedResolution.

himitsu 25. Sep 2022 12:13

AW: DUnit und Fließkommazahlen Problem
 
Verwende besser DUnitX, nicht mehr DUnit.

Das DUnit im Delphi 11.2 ist scheinbar 11 Jahre alt
und selbst https://sourceforge.net/projects/dunit/ ist seit 8 Jahren tot.

Wobei DUnitX, im Delphi mitgeliefert, ist auch 7 Jahre alt :wall:,
also besser gleich von https://github.com/VSoftTechnologies/DUnitX/


ich wüsste jetzt nichtmal, wo man hier die Fehler melden sollte. (von Emba erwarte icht keine Fehlerbehebung)

alleine diese eine Funktion:
Zitat:

Zitat von BugReport
bitte Delta beachten oder Math.SameValue verwenden
Delphi-Quellcode:
procedure TAbstractTest.CheckEquals( expected,
                                     actual  : extended;
                                     delta   : extended;
                                     msg     : string = '');
begin
  FCheckCalled := True;
  if delta = 0 then
    delta := DoubleResolution;
  if not ((expected = Infinity) and (actual = Infinity)) then
    if ((expected = Infinity) and (actual <> Infinity)) or
       ((expected <> Infinity) and (actual = Infinity)) or
       (abs(expected-actual) > delta) then
      FailNotEquals(FloatToStr(expected), FloatToStr(actual), msg, ReturnAddress);
end;
Aber falls wirklich jemand "genau" prüfen will, dann
Delphi-Quellcode:
procedure TAbstractTest.CheckEquals( expected,
                                     actual  : extended;
                                     delta   : extended;
                                     msg     : string = '');
begin
  FCheckCalled := True;
  if delta = NaN then
    delta := DoubleResolution;
  if not ((expected = Infinity) and (actual = Infinity)) then
    if ((expected = Infinity) and (actual <> Infinity)) or
       ((expected <> Infinity) and (actual = Infinity)) or
       (abs(expected-actual) > delta) then
      FailNotEquals(FloatToStr(expected), FloatToStr(actual), msg, ReturnAddress);
end;

procedure TAbstractTest.CheckEquals(expected, actual: extended; msg: string);
begin
  CheckEquals(expected, actual, NaN, msg);
end;

Zitat:

Delphi-Quellcode:
  if not ((expected = Infinity) and (actual = Infinity)) then

Was ist mit NaN und NegInfinity?


Zitat:

Delphi-Quellcode:
procedure TAbstractTest.CheckEquals( expected,
                                     actual  : extended;
                                     delta   : extended;
                                     msg     : string = '');
const
  Infinity   = 1.0 / 0.0;
begin

Warum wird Infinity hier neu deklariert, anstatt System.Math.Infinity zu verwenden?


TurboMagic 25. Sep 2022 13:44

AW: DUnit und Fließkommazahlen Problem
 
Danke für all die Tipps.

@himtsu: wo hast du die DoubleResolution Konstante her? In System.Math is eine drin,
aber im implementation Teil?! Wäre es nicht nützlich diese im Interface Teil zu haben?

himitsu 25. Sep 2022 14:20

AW: DUnit und Fließkommazahlen Problem
 
Aus SameValue kopiert :stupid: .... echt mal, hätte nicht damit gerechnet, dass die selbst sowas nicht öffentlich deklariert haben :wall:

TurboMagic 25. Sep 2022 14:43

AW: DUnit und Fließkommazahlen Problem
 
Nah dann stimm mal schnell dafür ab:
https://quality.embarcadero.com/browse/RSP-39532

;-)

himitsu 25. Sep 2022 15:00

AW: DUnit und Fließkommazahlen Problem
 
Bin grade auf die Idee gekommen eine neue Unit bei mir einzuführen.

h5u.stuffthatEmbarcaderoistooslowtoimplementthemselvesismorbidlyhidingortoostupidtofix.pas

und alles, was nur wegen ihrer Unfähigkeit existiert, dort reinzuschieben.



https://quality.embarcadero.com/browse/RSP-33368
für zwei fehlende Zeilen (Variablen auf 0 setzen), existiert bei uns nun ein Package, was in der IDE sich böse in das Laden der DFMs hookt
und im Programm sich beim TReader einschleicht.

TurboMagic 25. Sep 2022 15:16

AW: DUnit und Fließkommazahlen Problem
 
Zitat:

Zitat von himitsu (Beitrag 1512424)
Bin grade auf die Idee gekommen.

Ich kam auch gerade auf eine Idee, die lies sich aber nicht umsetzen, weil dein Postfach
bei der DP voll ist! :lol:

Kannst du das mal bitte zumindest etwas leeren?

himitsu 25. Sep 2022 15:28

AW: DUnit und Fließkommazahlen Problem
 
oder fragen, ob jemand es größer machen kann?

https://www.delphipraxis.net/issue-496/
:freak:


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:44 Uhr.
Seite 1 von 2  1 2      

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