![]() |
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; |
AW: floating point invalid operation: 10.1 vs. 10.2
Vielen Dank für die weiteren Vorschläge - die werde ich morgen in Ruhe ausprobieren.
Allerdings scheinen auch diese darauf abzuzielen, das mathematisch richtige Ergebnis zu erzielen, ich brauche aber dummerweise das falsche Ergebnis, das eines Überlaufs. Anders ausgedrückt: Ich brauch eine Funktion, welche bei dem Beispielswert 64536 dann 184,17 als Ergebnis auswirft und nicht 91267,69. Und nach den gegebenen Erklärungen wird es für mich immer mysteriöser, warum unter 10.1 keine Eception kommt - selbst bei eingeschalteter Bereichsprüfung. Gute Nacht miteinander! |
AW: floating point invalid operation: 10.1 vs. 10.2
Habe mal ein bischen rumprobiert:
Es sieht so aus, dass in 10.2 der Rückgabewert von
Delphi-Quellcode:
kein Word, sondern ein Integer ist. Wenn der Rückgabewert ein Word wäre, könnte der Überlauf-Wert ja nicht negativ werden und es gäbe keine Exception beim SQRT.
SQR(AWord)
Man kann das schön nachvollziehen, wenn man den Rückgabewert von SQR entsprechend castet:
Delphi-Quellcode:
var
AWord: Word; ADouble: Double; temp :Integer; // <---- begin AWord := 64536; temp := SQR(AWord); // -130072000 ADouble := SQRT(temp + temp); // floating point invalid operation end;
Delphi-Quellcode:
So bekommst du auch deinen richtigen falschen Wert 184,17.
var
AWord: Word; ADouble: Double; temp :Word; // <---- begin AWord := 64536; temp := SQR(AWord); // 16960 ADouble := SQRT(temp + temp); // 184,17 end; Anscheinend gibt D10.1 im Gegensatz zu 10.2 hier bei SQR gleich den Word-Wert 16960 zurück. |
AW: floating point invalid operation: 10.1 vs. 10.2
Super, das erzeugt genau die Werte, die ich brauche!
In der Ecke scheint sich auch noch mehr getan zu haben. So funktionieren in 10.2 anscheinend
Delphi-Quellcode:
{$FINITEFLOAT OFF}
und
Delphi-Quellcode:
Math.SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]);
nicht mehr. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:58 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