Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Nicht nachvollziehbare Invalid floating point operation (https://www.delphipraxis.net/155585-nicht-nachvollziehbare-invalid-floating-point-operation.html)

Fussball-Robby 29. Okt 2010 19:58

Delphi-Version: 7

Nicht nachvollziehbare Invalid floating point operation
 
Hey,
folgendes funktioniert (Zahlen kommen eigentlich von Funktionen, sind hier als Zahlen selbst eingefügt):
Delphi-Quellcode:
var
  X: Extended;
begin
  X := Round((5.4097598831e+17 / (2 * 13.685690504)) * 497);
  ShowMessage(FloatToStr(X));
Folgendes aber funktionert nicht, obwohl Image1.Height = 497 ist!
Delphi-Quellcode:
var
  X: Extended;
begin
  X := Round((5.4097598831e+17 / (2 * 13.685690504)) * Image1.Height);//<-EInvalidOp
  ShowMessage(FloatToStr(X));
Auch das geht nicht:
Delphi-Quellcode:
var
  X: Extended;
  P: Extended; //oder Integer
begin
  P := Image1.Height;
  X := Round((5.4097598831e+17 / (2 * 13.685690504)) * P);//<-EInvalidOp
  ShowMessage(FloatToStr(X));

Ich kann das absolut nicht nachvollziehen. Könnt ihr mir auf die Sprünge helfen?
P.S.: Wenn ich das e+17 auf e+16 runtersetze, funktioniert es. Trotzdem merkwürdig..

Luckie 29. Okt 2010 20:10

AW: Nicht nachvollziehbare Invalid floating point operation
 
Wo ist das merkwürdig? Der die Zahl ist einfach zu groß für den Wertebereich des Datentyps.

Fussball-Robby 29. Okt 2010 20:29

AW: Nicht nachvollziehbare Invalid floating point operation
 
Merkwürdig ist es, weil es funktioniert, wenn ich 497 als zahl in den Code schreibe. Setze ich allerdings Image1.Height ein, welches ebenfalls 497 ist, gibt es den Fehler. Und 10e+19 etc sollten für Extended sowieso kein problem bedeuten.

Satty67 29. Okt 2010 21:20

AW: Nicht nachvollziehbare Invalid floating point operation
 
Der Fehler ist der Datentyp für Round().

Delphi-Quellcode:
X := Round(10);
ergibt auch ein EInvalidOP.
Delphi-Quellcode:
X := Round(10.0);
ergibt kein EInvalidOP.

Wie bei Image1.Height wird die 10 zu einem Integer, Round erwartet aber einen Real-Typen (Double, Extended etc.).

Bei
Delphi-Quellcode:
X := Round((5.4097598831e+17 / (2 * 13.685690504)) * 497);
.
wurde 497 zu einem Extended, da hier an die anderen Konstanten angepasst wird (werden darf), die vom Compiler durch den Dezimalseparator bereits als Extended erkannt wurden.

***

Der Compiler wertet zuerst den Ausdruck aus und nimmt den einfachsten passenden Datentyp (Integer vor Real), danach kommt der Funktionsaufruf Round(). Das ist der Grund, warum der Compiler quasi dem Code ein Bein stellt.

Warum der Ausdruck
Delphi-Quellcode:
(5.4097598831e+17 / (2 * 13.685690504)) * Image1.Height
.
zu einem nicht umcastbaren Integer wird und
Delphi-Quellcode:
Round(Image1.Height)
.
vom Compiler zu einem Real gecastet wird, wäre dann meine nächste Frage ;)

Hawkeye219 29. Okt 2010 23:28

AW: Nicht nachvollziehbare Invalid floating point operation
 
Hallo,
Zitat:

Zitat von Fussball-Robby (Beitrag 1058557)
folgendes funktioniert (Zahlen kommen eigentlich von Funktionen, sind hier als Zahlen selbst eingefügt):
Delphi-Quellcode:
var
  X: Extended;
begin
  X := Round((5.4097598831e+17 / (2 * 13.685690504)) * 497);
  ShowMessage(FloatToStr(X));

Das funktioniert keineswegs. Solange man einen konstanten Ausdruck übergibt, versucht der Compiler diesen auszuwerten. Offenbar werden dabei nicht alle Fehler gemeldet (in diesem Fall die unmögliche Umwandlung des Extended-Wertes in einen ganzzahligen Wert), es wird stattdessen ein Fehlerwert zurückgegeben. Wenn der Ausdruck zur Laufzeit berechnet werden muss, meldet die RTL alle auftretenden Fehler:

Delphi-Quellcode:
var
  X, Y: Extended;
begin
  Y := Round(1E200);
  ShowMessage (FloatToStr(Y)); // liefert -9,22337203685478E18 = Min(Int64)
 
  X := 1E200;
  Y := Round(X);
  ShowMessage (FloatToStr(Y)); // liefert "Ungültige Gleitkommaoperation"
end;
Gruß Hawkeye

himitsu 29. Okt 2010 23:53

AW: Nicht nachvollziehbare Invalid floating point operation
 
wird direkt durch den Compiler ausgerechnet und dann direkt an Y übergeben, als Konstante:
Delphi-Quellcode:
Y := Round(1E200);
// oder
Y := 123 * 1E200;
wird erst zur Laufzeit ausgerechnet:
Delphi-Quellcode:
X := 1E200;

Y := Round(X);
// oder
Y := 123 * X;


Code:
Unit9.pas.29: Y := Round(1E200);
004B32BC 33C0             xor eax,eax
004B32BE 8945E0           mov [ebp-$20],eax
004B32C1 C745E400000080   mov [ebp-$1c],$80000000
004B32C8 66C745E83EC0     mov word ptr [ebp-$18],$c03e


Unit9.pas.32: X := 1E200;
004B32E9 C745F06DD112BB  mov [ebp-$10],$bb12d16d
004B32F0 C745F4BEC638A7   mov [ebp-$0c],$a738c6be
004B32F7 66C745F89742     mov word ptr [ebp-$08],$4297
Unit9.pas.33: Y := Round(X);
004B32FD DB6DF0           fld tbyte ptr [ebp-$10]
004B3300 E8E312F5FF      call @ROUND
004B3305 8945D4           mov [ebp-$2c],eax
004B3308 8955D8           mov [ebp-$28],edx
004B330B DF6DD4           fild qword ptr [ebp-$2c]
004B330E DB7DE0           fstp tbyte ptr [ebp-$20]
004B3311 9B              wait


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:29 Uhr.

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