::: nefzger dot at :::
    You are here: Pfeil //nefzger.at/~SoffyT/fakultaet.html

~/~SoffyT
Software:
    Pfeil ed
    Pfeil nf
    Pfeil gh
    Pfeil vg

Kontakt:
    Pfeil eMail


~/~MNe
Software:
    Pfeil IPing
    Pfeil IGrep
    Pfeil MaskMove
    Pfeil Puzzle
    Pfeil ZoomIn!

Kontakt:
    Pfeil eMail


~/
Links:
    Pfeil rOOt
    Pfeil Site History
    Pfeil Impressum

Kontakt:
    Pfeil eMail


What Is It?
What Is It?

Link List
Link List


Site Map
Site Map


search ::: nefzger dot at :::

powered by FreeFind
get notified of updates
?
powered by ChangeDetection

TRIANGLE productions
www.triangle.at

Ultima Online Portal
ultima.gatecentral.com

Free Website Promotion & Search Engine Submission
www.addpro.com



Site Stats
Site Stats

-- gh (-G-enerate -H-tml) v1.91 -- Copyright (c) 2002, 2005 SoffyT & MNe --

[ Abstrakt | Über Fakultäten | Das Programm 'nf' | Download | Kontakt ]

^ Abstrakt:

'nf' ist ein Programm

^ Über Fakultäten:

Mathematische -- meist kombinatorische -- Formel sind manchmal mit einem Ausrufezeichen ('!') versehen. Dies ist aber kein Ausdruck der Überraschung, sondern ein mathematischer Operator, der Fakultätszeichen genannt wird. Ein Fakultätszeichen folgt einer Formel oder einer natürlichen Zahl, und bedeutet, daß die Zahl mit allen natürlichen Zahlen, die kleiner als diese sind, multipliziert werden. Zum Beispiel 4! -- gesprochen als '4 Fakultät' -- ist das Produkt von 4x3x2x1.

Warum sind nun Fakultäten in der Kombinatorik und Wahrscheinlichkeitsrechnungen so wichtig? Die einfache Antwort lautet, daß n! die Anzahl der unterschiedlichen Möglichkeiten angibt, n Dinge in einer Reihe anzuordnen. Stellen wir uns hierfür folgendes Beispiel vor: wir haben 4 Personen und 4 Stühle, und fragen uns: wieviele Unterschiedliche Möglichkeiten gibt es, die Stühle zu besetzen? Logischerweise gibt es 4 Möglichkeiten, den ersten Stuhl zu besetzen. Nachdem nun Person und Stuhl 'aufgebraucht' sind, haben wir weitere 3 Möglichkeiten, den zweiten Stuhl zu besetzen (und somit 4x3 Möglichkeiten, die ersten beiden Stühle zu besetzen). Danach haben wir 2 weitere Möglichkeiten, den dritten Stuhl zu besetzen (und somit 4x3x2 Möglichkeiten, die ersten drei Stühle zu besetzen). Schließlich bleibt uns, für den letzten Stuhl, nur mehr eine Möglichkeit der Besetzung. Das Ergebnis lautet daher: wir haben 4! = 4x3x2x1 -- also 24 -- unterschiedliche Möglichkeiten, 4 Personen auf 4 Stühle zu setzen.

Mit der selben Überlegung kann man z.B. auch ermitteln, wie viele Möglichkeiten es gibt, 40 Spielkarten (wie sie -- in der Ausführung als Tarockkarten -- bei uns in Österreich z.B. für das sehr beliebte Tarock XXer-Rufen Verwendung finden) anzuordnen: wir haben genau 40! unterschiedliche Möglichkeiten, dies durchzuführen - eine bereits recht 'ansehliche' Zahl mit 45 Stellen (siehe Tabelle).

Interessant ist weiters, daß der Wert einer Fakultät auch näherungsweise bestimmt werden kann; dazu verwendet man die nach dem Mathematiker James Stirling (18. Jhdt) benannte Formel:

Stirling'sche Formel

Die Stirling'sche Formel ist insoferne recht eigenartig, da sie die zwei wohl bekanntesten transzendenten Zahlen pi (das Verhältnis zwischen dem Umfang und dem Durchmesser eines Kreises: 3,1415926..) und e (die Eulersche Zahl: 2,7182818..) verwendet. Der absolute Fehler (die Differenz zwischen dem wahren und dem angenähertem Wert einer Fakultät) wächst mit steigendem n; der relative Fehler (der absolute Fehler dividiert durch den wahren Wert) wird hingegen ständig kleiner.

Wie wir erkennen, ist die Berechnung des exakten Wertes einer Fakultät nicht kompliziert, aber mühsam, und das Ergebnis wird schnell sehr groß. Die Berechnung von z.B. 1.000! erfordert 'nur', daß einfach das Ergebnis von 1000x999x998x .. x3x2x1 berechnet wird; aber versuchen Sie das einmal mit Papier und Bleistift; das Ergebnis hat lächerliche 2.568 Stellen :-). Vor der Entwicklung von Computern war daher der Wert von Fakultäten nur bis zirka 300! bekannt; ausgenommen einer Handvoll größerer Fakultäten, von denen sich jemand die Mühe gemacht hat, diese auszurechnen.

Wie erwähnt haben Fakultäten haben im Besonderen die Eigenschaft, schnell sehr groß zu werden; eine Tatsache, welche durch die folgende Tabelle veranschaulicht wird:

n!# Ziffer(n)Ergebnis

1!11
2!12
3!16
5!3720
7!45040
10!73628800
20!192432902008176640000
30!33265252859812191058636308480000..
50!65304140932017133780436126081660..
70!101119785716699698917960727837216..
100!158933262154439441526816992388562..
200!375788657867364790503552363213932..
300!615306057512216440636035370461297..
500!1.135122013682599111006870123878542..
700!1.690242204012475027217986787509381..
1.000!2.568402387260077093773543702433923..
2.000!5.736331627509245063324117539338057..
3.000!9.131414935960343785408555686709308..
5.000!16.326422857792660554352220106420023..
7.000!23.878884200795696311224786499369689..
10.000!35.660284625968091705451890641321211..
20.000!77.338181920632023034513482764175686..
30.000!121.288275953724621938459937994216642..
50.000!213.237334732050959714483691547609407..
70.000!308.760117681241537969008158824292086..
100.000!456.574282422940796034787429342157802..


Fakultäten haben somit nichts magisches oder mystisches oder gar unverständliches, nur war es eben vor 60 oder 70 Jahren keinem Menschen möglich, den Wert von, zum Beispiel, 100.000! (exakt!, nicht über die Stirling'sche Formel) zu bestimmen.

^ Das Programm 'nf':

Der Compilerlauf:

~~
~~ brcc32 nf.verinfo.rc -fonf.verinfo.res
~~ dcc32 -B -CC -GD -H -W -$A+ -$B- -$C- -$D- -$L- -$Y- -$H+ 
-$I- -$J- -$O+ -$Q- -$R- -$T- -$U+ -$W- -$X+ -$Z4 nf.dpr
~~
Borland Delphi  Version 13.0  Copyright (c) 1983,99 Inprise Corporation
O:\Marcus\mne_Testverzeichnis\core_utilities\CmdLine_Utilities.pas(182)
O:\Marcus\mne_Testverzeichnis\core_utilities\Misc_Utilities.pas(1054)
O:\Marcus\mne_Testverzeichnis\bogus_classes\Fakultaet.pas(289)
nf.dpr(164)
1693 Zeilen, 0.27 Sekunden, 43864 Bytes Code, 2609 Bytes Daten.

Der Quelltext der Projektdatei ('nf.dpr', 11.543 Byte):

(*
 *                                                                                             .
 * Module name: nf.dpr; Module type: Delphi (console) project; Language: Object pascal;        .
 * Original developed with: Delphi 5 Enterprise; Portability: most likely down to Delphi 2;    .
 *                                                                                             .
 * Author: ~SoffyT (web:<http://www.nefzger.at/~SoffyT/>; mailto:<MissyQueen@nefzger.at>)      .
 * File created: Fri., 01.11.2002; Last modified: Thu., 03.02.2005                             .
 *                                                                                             .
 * Bug report: Pls. report all bugs, wishes, suggestions etc. to <BugReport@nefzger.at>.       .
 *                                                                                             .
 *  Purpose:                                                                                   .
 * ----------                                                                                  .
 *    Console wrapper for Fakultaet.pas                                                        .
 *                                                                                             .
 *)
(*
 *                                                                                             .
 * To compile with Delphi:                                                                     .
 *    (To do ..)                                                                               .
 * To compile with FPC:                                                                        .
 *    fpc -B -Sd -Op2 -Xs -XX -Fu"..\includes;..\core_utilities;..\bogus_classes" -FU"%TEMP%" nf.dpr -onf.fpc.exe            .
 *                                                                                             .
 *)
{$APPTYPE Console}
program
   nFakultaet; // AKA 'nf' or 'nf.dpr'                                                         .
{$INCLUDE '..\includes\Globals.inc'}
uses
   Windows,
   SysUtils,
{$IFDEF DelphiPascalCompiler}
   CmdLine_Utilities in '..\core_utilities\CmdLine_Utilities.pas',
   Misc_Utilities    in '..\core_utilities\Misc_Utilities.pas',
   Fakultaet         in '..\bogus_classes\Fakultaet.pas';
{$ENDIF}
{$IFDEF FreePascalCompiler}
   CmdLine_Utilities ,
   Misc_Utilities    ,
   Fakultaet         ;
{$ENDIF}
// -- Programm- & Versions-Info -------------------------------                                .
{$R 'nf.verinfo.res'}          // generiert mit VerGen.exe Copyright (c) 2002, 2004 ~MNe :-)   .
var
   Program_name : String;
   CmdLine_ok   : Integer;
// ------------------------------------------------------------                                .
const
   MAX_n     = 499999; // Max. Fakultät: 1/2 Million                                           .
   PROFILE_n = 15123;  // Diese Fakultät für's Profiling                                       .
var
   i : Integer;
   t : Cardinal;
   f : TFakultaet;
   s : String;
// ============================================================================                .
begin try
   // Vorspann des Programms                                                                   .
   Program_name := appGetApplicationFileName();
   CmdLine_ok := GetFirstInvalidSwitch(
      CheckCmdLineSwitches(  // Kommandozeile auswerten #1, "Lang-Form" ..                     .
         ['version','history',
          'quiet',
          'profile'],
         ['-'],
         [False,False,
          False,
          False],
         True),
      CheckCmdLineSwitches(  // Kommandozeile auswerten #2, "Kurz-Form" ..                     .
         ['v','h',
          'q',
          'p'],
         ['-','/'],
         [False,False,
          False,
          False]
         {$IFDEF FreePascalCompiler},False{$ENDIF}));
   WriteLn;
   WriteLn(Program_name,' -- ',resGetXVersionInfo(),', ',resGetXReleaseInfo(),', ',
      resGetXDateTimeInfo());
   Writeln(StringOfChar(' ',Length(Program_name)),' -- ',resGetXCopyrightInfo());
   WriteLn(StringOfChar(' ',Length(Program_name)),' -- ','(dbg) OS: ',
      sysGetWin32Version().w32ComposedName,'; CmdLineCnt: ',ParamCount(),'; CmdLineErg: ',
      CmdLine_ok);
   WriteLn;
   // Kommandozeile auswerten                                                                  .
   if (CmdLine_ok = CMDLINE_VALID) and
      ((ParamCount = 1) and ((CmdLineSwitch('v',['-','/'],False{$IFDEF FreePascalCompiler},False{$ENDIF}) > 0) or
                             (CmdLineSwitch('version',['-'],False,True) > 0))) then begin
      // Parameter '--version': keine weiteren Informationen anzeigen ..                       .
   // WriteLn('Exiting.');
      {$INCLUDE '.\all.motd.inc'}
   end else if (CmdLine_ok = CMDLINE_VALID) and
               ((ParamCount = 1) and ((CmdLineSwitch('h',['-','/'],False{$IFDEF FreePascalCompiler},False{$ENDIF}) > 0) or
                                      (CmdLineSwitch('history',['-'],False,True) > 0))) then begin
      // Parameter '-History': als Resource gelinkte History anzeigen ..                       .
      WriteLn(resGetXHistoryInfo());
   end else if (CmdLine_ok = CMDLINE_VALID) and
               ((ParamCount = 1) and ((CmdLineSwitch('p',['-','/'],False{$IFDEF FreePascalCompiler},False{$ENDIF}) > 0) or
                                      (CmdLineSwitch('profile',['-'],False,True) > 0))) then begin
      // Parameter '-p': Profiling der unterschiedlichen Methoden mit vorgegebenem N ..        .
      WriteLn('Profiling ',TFakultaet.GetBestM(),' different methodes by calculating ',
         fmtFormatNumber((1.0*PROFILE_n),0),'!:');
      WriteLn;
      for i := 1 to TFakultaet.GetBestM() do begin
         f := TFakultaet.Create();
         Write('Calculating ',fmtFormatNumber((1.0*PROFILE_n),0),'! /w methode #',i,' ..');
         t := GetTickCount();
         f.M := i;
         f.N := PROFILE_n;
         t := (GetTickCount()-t);
         if (f.NumDigits > 0) then begin
            // Berechnung ist OK - Ergebnis ausgeben ..                                        .
            WriteLn(' Done. Calculation needed ',fmtFormatNumber((t/1000),2),' second(s).');
            s := Copy(f.Result,1,100);
            WriteLn('  Result snapshot: ',Copy(s,1,50));
            WriteLn('                   ',Copy(s,51,50),' ..');
         end else begin
            // Berechnung ist fehlgeschlagen - Fehlernummer und -meldung ausgeben ..           .
            WriteLn(' Done, but the following error occured:');
            WriteLn('  Error ',f.NumDigits,': ',f.Result,'.');
         end;
         FreeAndNil(f);
      end;
   end else if (CmdLine_ok = CMDLINE_VALID) and
               ((ParamCount = 1) and (StrToIntDef(ParamStr(1),(-1)) > 0) and
                (StrToIntDef(ParamStr(1),(MAX_n + 1)) <= MAX_n)) then begin
      // Priorität des Programmes herabsetzen, damit der Compi weiter benutzt werden kann ..   .
      if not(SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS)) then
         WriteLn('SetPriorityClass() failed: ''',fmtFormatMessageFromSystem({$IFDEF FreePascalCompiler}MAX_CARDINAL,True{$ENDIF}),
            '''; will continue anyway.');
      if not(SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_LOWEST)) then
         WriteLn('SetThreadPriority failed: ''',fmtFormatMessageFromSystem({$IFDEF FreePascalCompiler}MAX_CARDINAL,True{$ENDIF}),
            '''; will continue anyway.');
      // Hier geht es los mit der Berechnung von N! ..                                         .
      f := TFakultaet.Create();
      Write('Wait ..');
      t := GetTickCount();
   // f.M := TFakultaet.GetBestM(); << wird im Konstruktor eh eingestellt ..                   .
      f.N := StrToInt(ParamStr(1));
      t := (GetTickCount()-t);
      if (f.NumDigits > 0) then begin
         // Berechnung ist OK - Ergebnis ausgeben ..                                           .
         WriteLn(' Done. ',fmtFormatNumber((1.0*f.N),0),'! has ',fmtFormatNumber(
            (1.0*f.NumDigits),0),' digits; calculation /w methode #',f.M,' needed ',
            fmtFormatNumber((t/1000),2),' second(s) and took (',fmtFormatNumber(
            (1.0*f.M_Iterations),0),'+',fmtFormatNumber((1.0*f.UC_Iterations),0),
            ') iteration(s).');
         WriteLn;
         WriteLn(fmtFormatNumber((1.0*f.N),0),'! = ',f.Result);
      end else begin
         // Berechnung ist fehlgeschlagen - Fehlernummer und -meldung ausgeben ..              .
         WriteLn(' Done, but the following error occured:');
         WriteLn('   Error ',f.NumDigits,': ',f.Result,'.');
      end;
      FreeAndNil(f);
   end else begin
      // Ungültigen Parameter / Schalter gefunden? -> Ausgabe desjenigen welchen ..            .
      if ((CmdLine_ok <> CMDLINE_VALID) or
          (ParamCount() > 0)) then begin
         if (CmdLine_ok <> CMDLINE_VALID) then
            WriteLn('Sorry! Unknown switch: ','''',ParamStr(CmdLine_ok),'''','.')
         else
            WriteLn('Sorry! Unknown or unsupported parameter: ',
               '''',ParamStr(ParamCount()),'''','.');
         WriteLn;
      end;
      // Angegebene Kommandozeile war wohl niX .. Usage-Meldung ausgeben ..                    .
      WriteLn('Usage: ',Program_name,' [N] {-q|--quiet} | {-v|--version} | {-h|' +
         '--history} | {-p|--profile}');
      WriteLn;
      WriteLn(' e.g.: ',Program_name,' 666');
      WriteLn;
      WriteLn('  N                  A number between 1 (min) and ',
         fmtFormatNumber((1.0*MAX_n),0),' (max).');
      WriteLn('  -q, /q, --quiet    Quiet: no additional output. (Unimplemented' +
         ' by now.)');
      WriteLn('  -v, /v, --version  Display version number only.');
      WriteLn('  -h, /h, --history  Display program/ version history.');
      WriteLn('  -p, /p, --profile  Profile the ',TFakultaet.GetBestM(),' diffe' +
         'rent implementations.');
      WriteLn;
      WriteLn('Hint(s): Parameters enclosed in ''[]'' are mandatory; parameters' +
         ' enclosed in ''{}'' are optional; parameters seperated by ''|'' exclu' +
         'de each other; ''<..>'' within a parameter means that *you* have to s' +
         'upply additional information.');
      WriteLn;
      WriteLn('Beware: While calculating 999! (2.565 digits: ''40238726007..'')' +
         ' only takes about 00:00,20 [mm:ss,hh], calculating 99.999! (456.569 d' +
         'igits: ''28242294079..'') takes about 59:25,50 [mm:ss,hh]! (System wa' +
         's a P3 @ 550 MHz /w 512 MB, NT 4, SP6a).');
      WriteLn;
      WriteLn('Bug report: Pls. report all bug(s) and/ or wishes, suggestions e' +
         'tc. to <BugReport@nefzger.at>, including the module name (which is: ''',
         Program_name,''') and module version (which is: ''',resGetXVersionInfo(),
         '''). Thank you.');
   end;
   Halt(0); // Normales Programmende, mit Exitcode 0 retour ..                                 .
except
   on e: Exception do begin
      WriteLn(' Fatal: Exception: ','''',e.Message,'''','; pls. contact the pro' +
         'grammer: <BugReport@nefzger.at>.');
      Halt(1); // Abnormales Programmende: irgendwo wurde (intern) eine Exception geworfen ..  .
   end;
end; {try} end. // {begin}                                                                     .

Der Quelltext der Klasse TFakultaet ('fakultaet.pas', 13.277 Byte):

(*
 *                                                                                             .
 * Module name: Fakultaet.pas; Module type: Delphi unit; Language: Object pascal;              .
 * Original developed with: Delphi 5 Enterprise; Portability: most likely down to Delphi 2;    .
 *                                                                                             .
 * Author: ~SoffyT (web:<http://www.nefzger.at/~SoffyT/>; mailto:<MissyQueen@nefzger.at>)      .
 * File created: Fri., 01.11.2002; Last modified: Fri., 17.01.2003                             .
 *                                                                                             .
 * Bug report: Pls. report all bugs, wishes, suggestions etc. to <bugreport@nefzger.at>.       .
 *                                                                                             .
 *  Purpose:                                                                                   .
 * ----------                                                                                  .
 *                                                                                             .
 *  Implemented classes:                                                                       .
 * ----------------------                                                                      .
 *    TFakultaet { = class (TObject) }                                                         .
 *                                                                                             .
 *)
unit
   Fakultaet;
// ----------                                                                                  .
   interface
// ----------                                                                                  .
type
   PArrayOfByte = ^TArrayOfByte;
   TArrayOfByte = packed array of Byte;
type
   TFakultaet = class
   { Private-Deklarationen }
   private
      FMethode: Integer;
      FN: Integer;
      FNErg: TArrayOfByte;
      FNErgLen: Integer;
      FMultiplyIterations: Int64;
      FUpdateCarryIterations: Int64;
      procedure Calculate_1 ({keine Parameter});
      procedure Calculate_2 ({keine Parameter});
      procedure Calculate_3 ({keine Parameter});
      procedure SetN (const AN: Integer);
      function GetResult ({keine Parameter}): String;
   { Protected-Deklarationen }
   protected
   { Public-Deklarationen }
   public
      constructor Create ({keine Parameter});
      destructor Destroy ({keine Parameter}); override;
      property M: Integer read FMethode write FMethode;
      property N: Integer read FN write SetN;
      property NumDigits: Integer read FNErgLen;
      property M_Iterations: Int64 read FMultiplyIterations;
      property UC_Iterations: Int64 read FUpdateCarryIterations;
      property Result: String read GetResult;
      class function GetBestM: Integer;
   { Published-Deklarationen }
   published
   end;
// ---------------                                                                             .
   implementation
// ---------------                                                                             .
const
   ERR_NO_SUCH_METHODE   = -1;
   ERR_BUFFER_OVERFLOW_1 = -2;
   ERR_BUFFER_OVERFLOW_2 = -3;
const
   MAX = (8*(1024*1024)); // Max. Anzahl an Ziffern                                            .
   NAN = Byte(-1);        // 'Flag' für ~N~ot ~A~ ~N~umber                                     .
// ----------------------------------------------------------------------------                .
// Berechnung von N! - Erste (AKA "originale") Implementierung                                 .
// ----------------------------------------------------------------------------                .
procedure TFakultaet.Calculate_1 ();
var
   i, c: Integer;
begin
   // Grundinitialisierung                                                                     .
   for i := High(FNErg) downto 0 do
      FNErg[i] := NAN;
   // Ergebnis für 1! initialisieren                                                           .
   FNErg[0] := 1;
   // Ergebnis für N! berechnen                                                                .
   if (FN > 1) then begin
      i := 2;
      while (i <= FN) do begin
         FNErgLen := 0;                // Index                                                .
         c := 0;                       // (Teil-) Ergebnis; akkumulativ; eine Art "Carry"      .
         // Berechne: (Bisheriges Ergebnis) * i                                                .
         while ((FNErgLen <= High(FNErg)) and (FNErg[FNErgLen] <> NAN)) do begin
            c := ((i * Integer(FNErg[FNErgLen])) + c);
            FNErg[FNErgLen] := Byte(c mod 10);
            c := (c div 10);
            Inc(FNErgLen);
            Inc(FMultiplyIterations);
         end;
         // Bei Buffer-Überlauf: Fehler setzen, raus hier                                      .
         if (FNErgLen > High(FNErg)) then begin
            FNErgLen := ERR_BUFFER_OVERFLOW_1;
            Exit;
         end;
         // Aktualisiere: angelaufener Übertrag c                                              .
         while ((FNErgLen <= High(FNErg)) and (c > 0)) do begin
            FNErg[FNErgLen] := Byte(c mod 10);
            c := (c div 10);
            Inc(FNErgLen);
            Inc(FUpdateCarryIterations);
         end;
         // Bei Buffer-Überlauf: Fehler setzen, raus hier                                      .
         if (FNErgLen > High(FNErg)) then begin
            FNErgLen := ERR_BUFFER_OVERFLOW_2;
            Exit;
         end;
         Inc(i);
      end;
   end else
      FNErgLen := 1;
end;
// ----------------------------------------------------------------------------                .
// Berechnung von N! - Zweite Implementierung:                                                 .
//    High(FNErg) wurde durch (MAX-1) ersetzt, da das Feld *IMMER*                             .
//    MAX Byte groß ist (indiziert von [0 .. (MAX-1)]                                          .
// ----------------------------------------------------------------------------                .
procedure TFakultaet.Calculate_2 ();
var
   i, c: Integer;
begin
   // Grundinitialisierung                                                                     .
   for i := (MAX - 1) downto 0 do
      FNErg[i] := NAN;
   // Ergebnis für 1! initialisieren                                                           .
   FNErg[0] := 1;
   // Ergebnis für N! berechnen                                                                .
   if (FN > 1) then begin
      i := 2;
      while (i <= FN) do begin
         FNErgLen := 0;                // Index                                                .
         c := 0;                       // (Teil-) Ergebnis; akkumulativ; eine Art "Carry"      .
         // Berechne: (Bisheriges Ergebnis) * i                                                .
         while ((FNErgLen <= (MAX-1)) and (FNErg[FNErgLen] <> NAN)) do begin
            c := ((i*Integer(FNErg[FNErgLen])) + c);
            FNErg[FNErgLen] := Byte(c mod 10);
            c := (c div 10);
            Inc(FNErgLen);
            Inc(FMultiplyIterations);
         end;
         // Bei Buffer-Überlauf: Fehler setzen, raus hier                                      .
         if (FNErgLen > (MAX-1)) then begin
            FNErgLen := ERR_BUFFER_OVERFLOW_1;
            Exit;
         end;
         // Aktualisiere: angelaufener Übertrag c                                              .
         while ((FNErgLen <= (MAX-1)) and (c > 0)) do begin
            FNErg[FNErgLen] := Byte(c mod 10);
            c := (c div 10);
            Inc(FNErgLen);
            Inc(FUpdateCarryIterations);
         end;
         // Bei Buffer-Überlauf: Fehler setzen, raus hier                                      .
         if (FNErgLen > (MAX-1)) then begin
            FNErgLen := ERR_BUFFER_OVERFLOW_2;
            Exit;
         end;
         Inc(i);
      end;
   end else
      FNErgLen := 1;
end;
// ----------------------------------------------------------------------------                .
// Berechnung von N! - Zweite Implementierung:                                                 .
//    High(FNErg) wurde durch (MAX-1) ersetzt, da das Feld *IMMER*                             .
//    MAX Byte groß ist (indiziert von [0 .. (MAX-1)]                                          .
// ----------------------------------------------------------------------------                .
procedure TFakultaet.Calculate_3 ();
var
   i, c: Integer;
begin
   // Grundinitialisierung                                                                     .
   for i := (MAX - 1) downto 0 do
      FNErg[i] := NAN;
   // Ergebnis für 1! initialisieren                                                           .
   FNErg[0] := 1;
   // Ergebnis für N! berechnen                                                                .
   if (FN > 1) then begin
      i := 2;
      while (i <= FN) do begin
         FNErgLen := 0;                // Index                                                .
         c := 0;                       // (Teil-) Ergebnis; akkumulativ; eine Art "Carry"      .
         // Berechne: (Bisheriges Ergebnis) * i                                                .
         while (FNErg[FNErgLen] <> NAN) do begin
            c := ((i * Integer(FNErg[FNErgLen])) + c);
            FNErg[FNErgLen] := Byte(c mod 10);
            c := (c div 10);
            Inc(FNErgLen);
            Inc(FMultiplyIterations);
         end;
         // Aktualisiere: angelaufener Übertrag c                                              .
         while (c > 0) do begin
            FNErg[FNErgLen] := Byte(c mod 10);
            c := (c div 10);
            Inc(FNErgLen);
            Inc(FUpdateCarryIterations);
         end;
         Inc(i);
      end;
   end else
      FNErgLen := 1;
end;
// ----------------------------------------------------------------------------                .
procedure TFakultaet.SetN (const AN: Integer);
begin
   if ((AN > 0) and (AN <> FN)) then begin
      FN := AN;
      FMultiplyIterations := 0;
      FUpdateCarryIterations := 0;
      case FMethode of                 // N! (sprich: 'N-Fakultät') berechnen                  .
         1: Calculate_1();
         2: Calculate_2();
         3: Calculate_3();
         else
            FNErgLen := ERR_NO_SUCH_METHODE;
      end;
   end;
end;
// ----------------------------------------------------------------------------                .
function TFakultaet.GetResult (): String;
var
   i, j: Integer;
begin
   if (FNErgLen < 0) then begin
      case FNErgLen of
         ERR_NO_SUCH_METHODE:
            Result := 'No such methode';
         ERR_BUFFER_OVERFLOW_1:
            Result := 'Digit buffer overflow while in loop #1 (calculating result)';
         ERR_BUFFER_OVERFLOW_2:
            Result := 'Digit buffer overflow while in loop #2 (updating result /w carry)';
         else
            Result := '';
      end;
   end else
      if (FN <= 0) then
         Result := '1'                 // negative Werte und '0' sind '1'                      .
      else begin
         i := 0;
         j := FNErgLen;
         SetLength(Result,j);
         while (i < FNErgLen) do begin // sonst: Ergebnis zu String zusammensetzen             .
            Result[j] := Chr(Ord('0') + FNErg[i]);
            Inc(i);
            Dec(j);
         end;
      end;
end;
// ----------------------------------------------------------------------------                .
constructor TFakultaet.Create ();
begin
   inherited;                          // Initialisierung:                                     .
   FMethode := TFakultaet.GetBestM();  //    .) beste (= schnellste) Implementierung           .
   FN := (-1);                         //    .) keine Fakultät                                 .
   SetLength(FNErg,MAX);               //    .) Speicherbuffer (für Berechnung) allokieren     .
   FNErgLen := 0;                      //    .) keine Ergebnislänge                            .
   FMultiplyIterations := 0;
   FUpdateCarryIterations := 0;
end;
// ----------------------------------------------------------------------------                .
destructor TFakultaet.Destroy ();
begin
   SetLength(FNErg,0);                 // Shutdown:                                            .
   inherited;                          //    .) Speicherbuffer freigeben                       .
end;
// ----------------------------------------------------------------------------                .
class function TFakultaet.GetBestM: Integer;
begin
   Result := 3; // Zugleich auch die "höchste" Methode:                                          .
              //    gültig sind 1 .. GetBestM                                                  .
end;
   // keine Initialisierung.                                                                   .
end.

Die ausführbare Datei -- auf Wunsch inklusive komplettem Quelltext -- steht in der Download-Sektion als ZIP-Archiv zur Verfügung.

^ Download:

Folgende Dateien stehen zum Download zur Verfügung:

Dateiname:Dateigröße:Beschreibung:

nf_ExeOnly.zip35.173 Byte'nf_ExeOnly.zip' für die Konsole, nur ausführbare Datei.
nfGUI_ExeOnly.zip232.551 Byte'nfGUI_ExeOnly.zip' (GUI wrapper für 'nf.exe' ['nf.exe' ist im Archiv inkludiert]), nur ausführbare Dateien.
nf_ExeAndSource.zip62.782 Byte'nf_ExeAndSource.zip' für die Konsole, ausführbare Datei & Quellcode (für Delphi5).
nfGUI_ExeAndSource.zip271.621 Byte'nfGUI_ExeAndSource.zip' (GUI wrapper für 'nf.exe' ['nf.exe' ist im Archiv inkludiert]), ausführbare Dateien & Quellcode (für Delphi5).


Zusätzliche Informationen:

  • Aktuelle Version von 'nf' ist /v/1.30.0.0227, Release /r/win32-x86-C-F-04.41.2, vom 05.10.2004, 16:35.
  • Aktuelle Version von 'nfGUI' ist /v/1.10.0.0143, Release /r/win32-x86-GUI-F-04.41.2, vom 05.10.2004, 16:35.
  • Die Archive mit Quellcode inkuldieren jeweils alle Source-Dateien (d.h. *.dpr, *.pas, *.dfm [*.dfm als Text-DFM]) und alle Resourcen (d.h. *.rc, *.res, *.ico). Das/ die Projekt(e) ist/ sind daher 'compile-ready' für Delphi 5 (und höher, denke ich :-). Portierung(en) bis hinunter zu Delphi 2 sollte(n) problemlos möglich sein. Das/ die Projekt(e) sind allerdings nicht für 16-Bit OS/ Compiler (d.h. z.B. Win32s, Delphi 1, Pascal ...) gedacht, aber who knows ...

^ Kontakt:

Web- & Mail-Adresse(n):




Valid XHTML! Valid CSS! Erstellt & gewartet von: Marcus F. Nefzger -- [ (2**5) == (18,31,14) ].
Site-Version: v0.83; zul. geändert am: Wed, 23 Feb 2005 09:03:56 GMT.
Generator: gh (-G-enerate -H-tml) v1.91, Copyright (c) 2002, 2005 SoffyT & MNe.