Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   fakultät ausrechnen - Exception wenn Wert zu groß wird (https://www.delphipraxis.net/136166-fakultaet-ausrechnen-exception-wenn-wert-zu-gross-wird.html)

Luckie 24. Jun 2009 21:38


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:
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;
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?

Fridolin Walther 24. Jun 2009 21:46

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.

Luckie 24. Jun 2009 21:48

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:

Desmulator 24. Jun 2009 21:49

Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
 
Zitat:

Zitat von Luckie
Delphi-Quellcode:
  if UpperLimit < 0 then
    raise ERangeError.Create('Wert ausserhalb des Wertebereichs');

Wäre es nicht besser hier eine EInvalidParam zu werfen? Es ist ja eigendlich kein RangeError sondern eher ein ungültige Operation. Die Mathunit macht das doch auch irgenwie :roll:

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. ( AllocConsole (?) oder einfach als Consolenprogramm kompelieren. ( {$APPTYPE CONSOLE} ) )

jfheins 24. Jun 2009 21:50

Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
 
Wie wärs damit:
Delphi-Quellcode:
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;
20! passt noch in den Int64, 21! nicht mehr => Fehler wird abgefangen bevor losrekursiert wird :stupid:

Fridolin Walther 24. Jun 2009 21:56

Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
 
Delphi-Quellcode:
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;
Wäre mein Vorschlag. Ohne Fehlerhandling. Keine Rekursion. Wirft ne Exception sobald es überläuft. Übrigens wie mein Vorredner bereits gesagt hat bei 21.

mirage228 24. Jun 2009 22:17

Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
 
Zitat:

Zitat von Fridolin Walther
Delphi-Quellcode:
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;
Wäre mein Vorschlag. Ohne Fehlerhandling. Keine Rekursion. Wirft ne Exception sobald es überläuft. Übrigens wie mein Vorredner bereits gesagt hat bei 21.

Oder einfach in den Projektoptionen die Überlaufprüfung einschalten ;)

Chemiker 24. Jun 2009 22:28

Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
 
Hallo Luckie,

Zitat:

Zitat von Luckie
Es kann natürlich zu einem Stacküberlauf kommen bevor der Wertebereich überwschritten wird

.

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

mirage228 24. Jun 2009 22:30

Re: fakultät ausrechnen - Exception wenn Wert zu groß wird
 
Zitat:

Zitat von Chemiker
Außerdem scheint mir Cardinal besser geeignet zu sein als int64, weil ohne Vorzeichen.

Gibt es nicht auch UInt64?

Viele Grüße

Chemiker 24. Jun 2009 22:41

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:
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;
Bis bald Chemiker


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:31 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