![]() |
Delphi-Version: 10.2 Tokyo
floating point invalid operation: 10.1 vs. 10.2
Der nachstehende Code läuft unter Delphi 10.1 ohne Problem, bei Delphi 10.2 kommt eine Exception (floating point invalid operation). Plattform ist jeweils Windows 32 Bit.
Delphi-Quellcode:
???
procedure TdlgMain.Test3;
var AWord: Word; ADouble: Double; begin AWord := 64536; ADouble := SQRT(SQR(AWord) + SQR(AWord)); end; Da ich den Source-Code von 10.1 nicht habe (Starter), kann ich nicht nachsehen, ob sich da etwas getan hat. |
AW: floating point invalid operation: 10.1 vs. 10.2
Die Hilfe zu SQR() sagt:
Zitat:
Bei 10.1 gibt es da zwar keine Exception, aber das Ergebnis stimmt leider auch nicht: 64.536² + 64.536² = 8.329.790.592
Delphi-Quellcode:
var
AWord: Word; begin AWord := 64536; Writeln(SQR(AWord) + SQR(AWord)); // => 33920 end; |
AW: floating point invalid operation: 10.1 vs. 10.2
Hallo Uwe,
danke für die Erläuterung - das hatte ich mir schon gedacht. Die Frage ist nur: Wie bekomme ich es vorerst hin, dass auch unter 10.2 keine Exception kommt? Und was hat sich denn zwischen 10.1 und 10.2 geändert? Der Hintergund: Ich nutze das als eine Art Zufalls-Generator für einen Graphik-Effekt, den ich zufällig entdeckt habe. Das hat natürlich mit sauberer Programmierung überhaupt nichts zu tun, aber ich habe das bislang noch nicht anderweitig nachbauen können. |
AW: floating point invalid operation: 10.1 vs. 10.2
Statt Word Cardinal nehmen oder einen Typen, der in der Lage ist, das Ergebnis aufzunehmen?
Oder ganz grausilig:
Delphi-Quellcode:
procedure TdlgMain.Test3;
var AWord: Word; ADouble: Double; ATemp: Double; begin AWord := 64536; ATemp := SQR(AWord + 0.0); // Das Quadrat muss man nicht zweimal berechnen // und + 0.0 macht aus dem Word 'nen Fließkommawert. ADouble := SQRT(ATemp + ATemp); end; |
AW: floating point invalid operation: 10.1 vs. 10.2
So kommt keine Exception, aber der Wert von ADouble ist natürlich anders und der Effekt klappt nicht.
Um den Effekt nachzubauen, müsste ich verstehen, was genau passiert, wenn bei 10.1 keine Exception kommt - das tue ich derzeit noch nicht. Es kommen aber immer die selben 'falschen'/'richtigen' Werte raus. |
AW: floating point invalid operation: 10.1 vs. 10.2
Dann berechne doch das Ergebnis einmal "zu Fuß" und vergleiche es mit dem Ergebnis ohne Exception. Stimmen die überein?
Wenn es so ist, wie Uwe es beschrieb, ist das Berechnungsergebnis, bei der Variante ohne Exception, schlicht und einfach falsch. Oder anders:
Delphi-Quellcode:
Wenn ich da jetzt nicht zuviele Schreib- und Denkfehler drinne haben sollte, so wären drei identische Ergebnisse identischer Berechnungen mit unterschiedlichen Datentypen zu erwarten.
var
AWord: Word; AWord2: Word; ACardinal: Cardinal; ADouble1: Double; ADouble2: Double; ADouble3: Double; begin AWord := 64536; ACardinal := 64536; ADouble1 := 64536; AWord := SQR(AWord); ACardinal := SQR(ACardinal); ADouble1 := SQR(ADouble1); ADouble1 := SQRT(ADouble1 + ADouble1); ADouble2 := SQRT(AWord + AWord); ADouble3 := SQRT(ACardinal + ACardinal); MessageDlg(Format('1. %f%s2. %f%s3.%f', ADouble1,#13,ADouble2,#13,ADouble3]),mtInformation,[mbOk],0); end; Frage: Ist dem (bei der Variante ohne Exception) so? |
AW: floating point invalid operation: 10.1 vs. 10.2
Zitat:
|
AW: floating point invalid operation: 10.1 vs. 10.2
@Delphi.Narium
Danke für deine Mühe, aber das ist es leider noch nicht. Zwar bekomme ich bei dem nachstehenden Code keinen Floating Point Fehler mehr, dafür jetzt einen Integer-Überlauf.
Delphi-Quellcode:
Unter 10.1 enthält ADouble den 184,17. Mathematisch korrekt wäre natürlich 91267,69
var
AWord: Word; ADouble: Double; ACardinal: Cardinal; begin AWord := 64536; ACardinal := SQR(AWord); ADouble := SQRT(ACardinal + ACardinal); end; @gammatester Warum ich den Effekt haben will? Weil man damit tolle Bilder erstellen kann. Die von dir vorgeschlagene Vorgehensweise bringt auch nicht das gewünschte Ergebnis. Das alles ist übrigens unabhängig davon, ob die Bereichs-Prüfung an oder ausgeschaltet ist. |
AW: floating point invalid operation: 10.1 vs. 10.2
Delphi-Quellcode:
:?:
AWord := 64536;
ADouble1 := Sqrt(Cardinal(Sqr(Word(AWord))) * 2); ADouble2 := Sqrt(Cardinal(Sqr(Integer(AWord))) * 2); ADouble3 := Sqrt(Cardinal(Sqr(Cardinal(AWord))) * 2); |
AW: floating point invalid operation: 10.1 vs. 10.2
Zitat:
Am sichersten fährst du, wenn AWord gleich als Double oder Extended deklariert wird.
Delphi-Quellcode:
Du kannst es dem Compiler aber auch leichter machen und es gleich so schreiben:
var
AWord: Double; ADouble: Double; begin AWord := 64536; ADouble := SQRT(SQR(AWord) + SQR(AWord)); end;
Delphi-Quellcode:
AWord := 64536;
ADouble := SQRT(2)*AWord; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:42 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