![]() |
fakultät ausrechnen - Exception wenn Wert zu groß wird
Ich spieöle gerade etwas mit einer Funktion zur Berechnung der Fakultät rum:
Delphi-Quellcode:
Wenn der Wert zur groß wird, wird leider ein Stacküberlauf ausgelöst. Für den Benutzer ist das aber eine eher unverständliche Fehlermeldung, deswegen wollte ich, wenn der Wertebereich überschritten wird eine ERangeError Exception auslösen. Nur leider scheint da snicht zu funktionieren, weil ich die Exception erst werfen, wenn das Kind schon in den Brunnen gefallen ist. Wie kann ich das lösen?
function fakultaet(UpperLimit: Int64): Int64;
begin if UpperLimit < 0 then raise ERangeError.Create('Wert ausserhalb des Wertebereichs'); if (UpperLimit = 0) or (UpperLimit = 1) then result := 1 else result := fakultaet(UpperLimit - 1) * UpperLimit; if result = High(Int64) then raise ERangeError.Create('Wert ausserhalb des Wertebereichs'); end; |
Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
Hmmm ... vielleicht steh ich ja aufm Schlauch, aber was hat die RangeException mit dem Stacküberlauf zu tun, der wahrscheinlich dadurch verursacht wird, daß für weitere Funktionsstacks kein Platz mehr ist auf Grund der hohen Rekursionstiefe.
|
Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
Ja das stimmt. Es kann natürlich zu einem Stacküberlauf kommen bevor der Wertebereich überwschritten wird. :gruebel:
|
Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
Zitat:
Naja nun zum Problem, du wirst mit der Fakultät ja nie genau High(Int64) erreichen, dahher musst du vorher berechnen, was die größt mögliche Fakultät ist und dann vorher prüfen ob UpperLimit genau diesen Wert hat. Fakultät von 4 ist ja 1 * 2 * 3 * 4, also benutz einfach den Debugger und finde herraus, welchen Wert UpperLimit hat, bevor es zu dem Fehler kommt. Könntest z.B. auch ne Konsole allocen und dann mit WriteLn jedes mal UpperLimit ausgeben, das was am Ende da steht ist der gesuchte Wert. ( ![]() |
Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
Wie wärs damit:
Delphi-Quellcode:
20! passt noch in den Int64, 21! nicht mehr => Fehler wird abgefangen bevor losrekursiert wird :stupid:
function fakultaet(n: Int64): Int64;
begin if n < 0 or n > 20 then raise ERangeError.Create('Wert ausserhalb des Wertebereichs'); if (n = 0) or (n = 1) then result := 1 else result := fakultaet(n - 1) * n; end; |
Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
Delphi-Quellcode:
Wäre mein Vorschlag. Ohne Fehlerhandling. Keine Rekursion. Wirft ne Exception sobald es überläuft. Übrigens wie mein Vorredner bereits gesagt hat bei 21.
function fakultaet_nonrecursive(UpperLimit: Int64) : Int64;
var i : Int64; begin Result := 1; i := 2; while i <= UpperLimit do begin if Result * i < Result then raise Exception.Create('Integerüberlauf!'); Result := Result * i; inc(i); end; end; |
Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
Zitat:
|
Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
Hallo Luckie,
Zitat:
das hat aber weniger mit dem Stack zu tun, als vielmehr mit der Registergröße. Außerdem scheint mir Cardinal besser geeignet zu sein als int64, weil ohne Vorzeichen. Bis bald Chemiker |
Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
Zitat:
Viele Grüße |
Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
Hallo mirage228,
dann ist die Berechnung, aber nicht mehr nur mit Registern durchzuführen bei 64Bit.
Delphi-Quellcode:
Bis bald Chemiker
function ASMFacIterativ(n: word): Cardinal;
asm PUSH ECX CMP EAX, 20 JG @@ZuViel CMP EAX, 1 JLE @@NullOderEins MOV ECX, EAX DEC ECX @@Weiter: MUL ECX LOOP @@Weiter JMP @@Schluss @@ZuViel: XOR EAX, EAX JMP @@Schluss @@NullOderEins: // Hier ladet er bei -Zahlen, bei 0 und bei 1 CMP EAX, 0 JE @@MacheEins CMP EAX, 1 JE @@MacheEins MOV EAX, 0 JMP @@Schluss @@MacheEins: OR EAX,1 @@Schluss: POP ECX end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:44 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