Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Wie benutze ich die Unit BigNum?


jsbach - Mi 13.04.11 12:11
Titel: Wie benutze ich die Unit BigNum?
Hallo,
hat jemand Erfahrung mit der Unit BigNum? Ich würde sie gerne auf meinen Algorithmus anwenden, habe aber keinen Schimmer wie ich da vorgehen muss. Kann mir jemand dabei helfen?

Dank und Gruß,
Mike


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
var
  Form1: TForm1;
  u,k,i,j,b: integer;
  a, m: extended;
  Liste: TStringList;
  g: array[-100..100, -100..100of extended;

implementation
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin

  Liste:=TStringList.Create;

  // alle Arrays auf Null setzen
  j:=-100;
  repeat
    i:=-100;
    repeat g[i,j]:=0; i:=i+1until i>100;
    j:=j+1;
  until j>100;  

  // u = 6..10 zur Ininitialisierung des Algorithmus
  g[1,6]:=1;  g[2,6]:=1;  g[3,6]:=3;  g[4,6]:=12;
  g[1,7]:=1;  g[2,7]:=1;  g[3,7]:=2;  g[4,7]:=7;  g[5,7]:=30;
  g[1,8]:=1;  g[2,8]:=2;  g[3,8]:=2;  g[4,8]:=5;  g[5,8]:=19; g[6,8]:=85;
  g[1,9]:=1;  g[2,9]:=2;  g[3,9]:=3;  g[4,9]:=3;  g[5,9]:=9;  g[6,9]:=37;  g[7,9]:=173;
  g[1,10]:=1; g[2,10]:=3; g[3,10]:=5; g[4,10]:=7; g[5,10]:=7; g[6,10]:=23; g[7,10]:=99; g[8,10]:=476;




  u:=11;
  repeat
                  g[u-5,u]   :=  g[u-7,u-5];
                  g[u-6,u]   :=  g[u-5,u];

    k:=6;  repeat g[u-k-1,u] :=  g[u-k,u] -g[u-8,u-5]; k:=k+1until k>8;

    k:=8;  repeat g[u-k-2,u] := -g[u-k,u] +2*g[u-k-1,u] +g[u-9,u-5]; k:=k+1until k>10;

    k:=10repeat g[u-k-3,u] :=  g[u-k,u] -3*g[u-k-1,u] +3*g[u-k-2,u] -g[u-k,u-5]; k:=k+1until k>13;


    i:=1; g[u-4,u]:=0; g[u-3,u]:=0; g[u-2,u]:=0;
    repeat
      g[u-4,u]:=g[u-4,u]+g[i,u];
      g[u-3,u]:=g[u-3,u]+g[i,u]*(u-i-2);
      g[u-2,u]:=g[u-2,u]+g[i,u]*(u-i-2)*(u-i+3)/2;
      i:=i+1;
    until i>u-5;


    u:=u+1;
  until u>17;




  u:=18;
  repeat
                  g[u-5,u]   :=  g[u-7,u-5] -g[u-17,u-12]*g[10,12];
                  g[u-6,u]   :=  g[u-5,u];

    k:=6;  repeat g[u-k-1,u] :=  g[u-k,u] -g[u-8,u-5] +g[u-17,u-12]*g[9,12]; k:=k+1until k>8;

    k:=8;  repeat g[u-k-2,u] := -g[u-k,u] +2*g[u-k-1,u] +g[u-9,u-5] -g[u-17,u-12]*g[8,12]; k:=k+1until k>10;

    k:=10repeat g[u-k-3,u] :=  g[u-k,u] -3*g[u-k-1,u] +3*g[u-k-2,u] -g[u-k,u-5] +g[u-17,u-12]*g[17-k,12]; k:=k+1until k>25;


    i:=1; g[u-4,u]:=0; g[u-3,u]:=0; g[u-2,u]:=0;
    repeat
      g[u-4,u]:=g[u-4,u]+g[i,u];
      g[u-3,u]:=g[u-3,u]+g[i,u]*(u-i-2);
      g[u-2,u]:=g[u-2,u]+g[i,u]*(u-i-2)*(u-i+3)/2;
      i:=i+1;
    until i>u-5;


    u:=u+1;
  until u>50;




  u:=11;
  repeat
    Liste.Add(Format('%d %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f',
    [ u, (g[1,u]),  (g[2,u]),  (g[3,u]),  (g[4,u]),  (g[5,u]),  (g[6,u]),  (g[7,u]),  (g[8,u]),  (g[9,u]),  (g[10,u]),
         (g[11,u]), (g[12,u]), (g[13,u]), (g[14,u]), (g[15,u]), (g[16,u]), (g[17,u]), (g[18,u]), (g[19,u]), (g[20,u]),
         (g[21,u]), (g[22,u]), (g[23,u]), (g[24,u]), (g[25,u]), (g[26,u]), (g[27,u]), (g[28,u]), (g[29,u]), (g[30,u]),
         (g[31,u]), (g[32,u]), (g[33,u]), (g[34,u]), (g[35,u]), (g[36,u]), (g[37,u]), (g[38,u]), (g[39,u]), (g[40,u]),
         (g[41,u]), (g[42,u]), (g[43,u]), (g[44,u]), (g[45,u]), (g[46,u]), (g[47,u]), (g[48,u]), (g[49,u]), (g[50,u]) ]));

    u:=u+1;
  until u>50;

  Liste.SaveToFile('F:\LISTE.txt');

  close;
end;


Gammatester - Mi 13.04.11 12:58

Da Dein Beitrag ja die Fortsetzung von Große Zahlen in zweidimensionalen Array speichern ist, wäre es vielleicht sinnvoll zu beschreiben, was da eigentlich gemacht wird, bzw. warum Dir die Extendend-Zahlen nicht reichen. Es gibt (mindestens) drei Möglichkeiten:

1. Zu große Zahlen
2. Zu große Genauigkeits-Ansprüche
3. Instabiler Algorithmus

Wichtig ist auch, ob Du Fließkomma- oder Ganzahlen brauchst.


jsbach - Mi 13.04.11 14:53

Ich möchte den Algorithmus auf einen großen Zahlenbereich ausweiten, also den 2D-Array, der jetzt als extended deklariert ist, soll größere Zahlen als 18 Stellen fassen. Der Algorithmus läuft im jetzigen Zahlenbereich bis u=46, danach wird gerundet. Alle Zahlen sind ganzzahlig und es wird nur mit den Grundrechenarten gerechnet.


Gammatester - Mi 13.04.11 16:07

Wenn Du keine negativen Zahlen brauchst ist es relativ einfach mit TBignumber-Arrays zu arbeiten (diese arbeiten IMO mit vorzeichenlosen Langzahlen):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
  M: array[-4..-21..3of TBignumber;
begin
  M[-3,2] := BMD_StrToBigNum('12345',false);
  M[-2,1] := BMD_StrToBigNum('56',false);
...
  BMD_BigNumToStr(M[-2,1],false);
end;
Wenn Du das allerdings das volle Programm mit den TSJBigNumber-Klassen benötigst, kann ich Dir bei Bignum nicht weiterhelfen, da ich zB nicht weiß, wie man sinnvoll ein Array[..] of TSJBigNumber (und seine einzelnen Elemente) erzeugt und belegt.


delfiphan - Mi 13.04.11 20:59

Ich hatte mal einen Adapter geschrieben, womit man BigInts verwenden kann wie ganz gewöhnliche Integers.

(Für die Veröffentlichung hatte ich vorausgesetzt, dass BenBE seine Lizenz anpasst. Dies ist bislang nicht geschehen. Die Lizenz macht für mich keinen Sinn, weil es gewisse Arten von Verwendungen an die Existenz von BenBE koppelt)


BenBE - Mi 13.04.11 21:29

Sorry. nach meiner Rückkehr aus meinem Urlaub ist noch einiges liegengeblieben. Hatte ja aber per PN schon etwas dazu gesagt.


jsbach - Do 14.04.11 20:38

Also, das mit dem Adapter klingt interessant. Darüber würde ich gerne mehr erfahren. Der Quelltext von Gammatester hilft mir nur bedingt. Ich ersetze in Var extended durch TBignumber, und ... dann hörts bei mir auch schon auf.
Trotzdem danke erstmal.


jsbach - Mo 18.04.11 23:15

Hi, hab jetzt so weit alles verstanden und benutzen können. Das Rechnen funktioniert wohl, aber bei der Ausgabe gibt es einen Fehler, und zwar bei "While (Num[0] <> 0) Or (Length(Num) <> 1) Do" in der Funktion:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
Function BMD_BigNumToStr(Num:TBigNumber; HexOutput: Boolean):String;
var
    B, R:TBigNumber;
    X:Integer;
    S:String;
Begin
    Result := '';
    IF HexOutput then
    Begin
        BM_Optimize(Num);
        For X := 0 to High(Num) do
            Result := IntToHex(Num[X], 2) + Result;
        While Length(Result) <> 0 do
            If Result[1] <> '0' Then
                Break
            else
                Delete (Result, 11);
        If Result = '' Then
            Result := '0';
    end
    else
    begin
        SetLength(B, 1);
        B[0] := 10;
        S := Screen.ActiveForm.Caption;
        While (Num[0] <> 0Or (Length(Num) <> 1Do
        Begin
            BM_Assign(R, BM_DivMod(Num, B));
            Result := IntToStr(R[0]) + Result;
            Screen.ActiveForm.Caption := S + ' (' + IntToStr (Length(Num)) + ' Bytes zur Konvertierung übrig)';
        end;
        Screen.ActiveForm.Caption := S;
    end;
end;



Meine Ausgabe sieht so aus:
u:=11;
repeat
Liste.Add(Format('%d %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f',
[ u,
BMD_BigNumToStr(g[1,u],false),
BMD_BigNumToStr(g[2,u],false),
BMD_BigNumToStr(g[3,u],false),
usw.

Liegt es vielleicht an dem %.0f Format?


Gammatester - Di 19.04.11 09:10

%f gibt einen Fließkommawert im Fix-Format aus! Wenn Du überhaupt format benutzen willst, solltest Du %s nehmen, da BMD_BigNumToStr ja Strings liefert. Übrigens wäre %f auch so nicht besonders sinnvoll, da die BigNums ja Ganzzahlen sind und Integer normalerweise mit %d formatiert werden.


jsbach - Di 19.04.11 13:22

So, es wird zwar gerechnet, aber irgndwie kommt nur Murgs dabei heraus. Ich zeige mal wie ich den Algorithmus umgeschrieben habe. Ursprünglich sah er so aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
var
  Form1: TForm1;

  u,k,i,j,b: integer;
  a, m: extended;
  Liste: TStringList;
  g: array[-100..100, -100..100of extended;

implementation
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin

  Liste:=TStringList.Create;

  // alle Arrays auf Null setzen
  j:=-100;
  repeat
    i:=-100;
    repeat 
      g[i,j]:=0
      i:=i+1
    until i>100;
    j:=j+1;
  until j>100;

  // u = 6..10 als Startwerte
  g[1,6]:=1;  g[2,6]:=1;  g[3,6]:=3;  g[4,6]:=12;
  g[1,7]:=1;  g[2,7]:=1;  g[3,7]:=2;  g[4,7]:=7;  g[5,7]:=30;
  g[1,8]:=1;  g[2,8]:=2;  g[3,8]:=2;  g[4,8]:=5;  g[5,8]:=19; g[6,8]:=85;
  g[1,9]:=1;  g[2,9]:=2;  g[3,9]:=3;  g[4,9]:=3;  g[5,9]:=9;  g[6,9]:=37;  g[7,9]:=173;
  g[1,10]:=1; g[2,10]:=3; g[3,10]:=5; g[4,10]:=7; g[5,10]:=7; g[6,10]:=23; g[7,10]:=99; g[8,10]:=476;

  u:=11;
  repeat
    m:=floor((u-6)/12);

    k:=5
      a:=0;
      b:=1;
      repeat 
        a:= a + g[u-12*b-5,u-12*b]*g[12*b-2,12*b]; 
        b:=b+1
      until b>m;
      g[u-k,u]:= g[u-7,u-5] - a;
      g[u-k-1,u]:= g[u-5,u];

    k:=6
      a:=0
      b:=1
      repeat a:= a + g[u-12*b-5,u-12*b]*g[12*b-3,12*b]; 
        b:=b+1
      until b>m;
      repeat
        g[u-k-1,u]:= g[u-k,u] - g[u-8,u-5] + a; k:=k+1;
      until k>8;

    
    .....


    i:=1
    g[u-4,u]:=0
    g[u-3,u]:=0
    g[u-2,u]:=0;
    repeat
      g[u-4,u]:=g[u-4,u]+g[i,u];
      g[u-3,u]:=g[u-3,u]+g[i,u]*(u-i-2);
      g[u-2,u]:=g[u-2,u]+g[i,u]*(u-i-2)*(u-i+3)/2;
      i:=i+1;
    until i>u-5;

    u:=u+1;
  until u>100;


  u:=11;
  repeat
    Liste.Add(Format('%d %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f',
    [ u, (g[1,u]),  (g[2,u]),  (g[3,u]),  (g[4,u]),  (g[5,u]),  (g[6,u]),  (g[7,u]),  (g[8,u]),  (g[9,u]),  (g[10,u]),
         (g[11,u]), (g[12,u]), (g[13,u]), (g[14,u]), (g[15,u]), (g[16,u]), (g[17,u]), (g[18,u]), (g[19,u]), (g[20,u]),
         (g[21,u]), (g[22,u]), (g[23,u]), (g[24,u]), (g[25,u]), (g[26,u]), (g[27,u]), (g[28,u]), (g[29,u]), (g[30,u]),
         (g[31,u]), (g[32,u]), (g[33,u]), (g[34,u]), (g[35,u]), (g[36,u]), (g[37,u]), (g[38,u]), (g[39,u]), (g[40,u]),
         (g[41,u]), (g[42,u]), (g[43,u]), (g[44,u]), (g[45,u]), (g[46,u]), (g[47,u]), (g[48,u]), (g[49,u]), (g[50,u]) ]));

    u:=u+1;
  until u>100;


  Liste.SaveToFile('F:\MIKES LISTE 2.txt');

  close;


Daraus wurde jetzt folgendes. Ich habe den Array g und die Variable a als TBignumber deklariert. Die gesamte BigNum Bibliothek habe ich in meine unit kopiert (hier jetzt weggelassen), da ich nicht wusste wie man sie sonst benutzt.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
var
  Form1: TForm1;

  u,i,j,b,k: integer;
  a: TBignumber;
  m: extended;
  Liste: TStringList;
  g: array[-100..100, -100..100of TBignumber;


procedure TForm1.Button1Click(Sender: TObject);
begin

  Liste:=TStringList.Create;

  // alle Arrays auf Null setzen
  j:=-100;
  repeat
    i:=-100;
    repeat
      g[i,j]:=BMD_StrToBigNum('0',false);
      i:=i+1;
    until i>100;
    j:=j+1;
  until j>100;

  // u = 6..10 als Startwerte
  g[1,6]:=BMD_StrToBigNum('1',false);  ..... u.s.w


  u:=11;
  repeat
    m:=floor((u-6)/12);

    k:=5;
      a:=BMD_StrToBigNum('0',false);
      b:=1;
      repeat
        a:= BMD_StrToBigNum('a + g[u-12*b-5,u-12*b]*g[12*b-2,12*b]',false);
        b:=b+1;
      until b>m;
      g[u-k,u]:= BMD_StrToBigNum('g[u-7,u-5] - a',false);
      g[u-k-1,u]:= BMD_StrToBigNum('g[u-5,u]',false);

    k:=6;
      a:=BMD_StrToBigNum('0',false);
      b:=1;
      repeat
        a:= BMD_StrToBigNum('a + g[u-12*b-5,u-12*b]*g[12*b-3,12*b]',false);
        b:=b+1;
      until b>m;
      repeat
        g[u-k-1,u]:= BMD_StrToBigNum('g[u-k,u] - g[u-8,u-5] + a',false);
        k:=k+1;
      until k>8;


    .....


    i:=1;
    g[u-4,u]:=BMD_StrToBigNum('0',false);
    g[u-3,u]:=BMD_StrToBigNum('0',false);
    g[u-2,u]:=BMD_StrToBigNum('0',false);
    repeat
      g[u-4,u]:=BMD_StrToBigNum('g[u-4,u]+g[i,u]',false);
      g[u-3,u]:=BMD_StrToBigNum('g[u-3,u]+g[i,u]*(u-i-2)',false);
      g[u-2,u]:=BMD_StrToBigNum('g[u-2,u]+g[i,u]*(u-i-2)*(u-i+3)/2',false);
      i:=i+1;
    until i>u-5;

    u:=u+1;
  until u>100;


  u:=11;
  repeat
    ...Ausgabe...


Flamefire - Di 19.04.11 13:59

Ganz ehrlich: Was erwartest du von diesem Befehl?

Delphi-Quelltext
1:
BMD_StrToBigNum('g[u-4,u]+g[i,u]',false);                    

StrToBigNum wandelt einen String in eine Zahl um, so wie StrToInt
für sowas gibt es dann BMD_Add

Besser wäre (schonmal wegen der Unterstützung negativer Zahlen) die Klassenvariante davon TSJBigNum oder so. Gibt es auch dort und funktioniert genauso. Nur dass du halt immer erst eine Instanz anlegen musst (mit TSJBigNum.Create) Dann hast du Methoden wie bigNum.Add(otherBigNum) und schon ist das ganze einfacher


Gammatester - Di 19.04.11 14:16

Das wird so nicht funktionieren. Du rechnest ja immer noch die Ausdrücke als extended aus und wandelst sie anschließend nach BigNum. Wenn extended reichen würde, wäre das überflüssig ansonsten falsch. Richtig wäre folgendes: definierst alle im Algorithmus verwendete Variablen als Bignum und rechnest mit den Bignumfunktionen, (also zB z := x + y wird zu z := BM_Add(x, y)) oder etwas konkreter:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  g: array[-100..100, -100..100of TBignumber;
  a,m: TBignumber;
begin
  //...
  //zb  wird g[u-k,u]:= g[u-7,u-5] - a; zu
  g[u-k,u]:= BM_Sub(g[u-7,u-5], a);
  //...
end;

Ich vermute alllerdings, daß selbst daß nicht richtig funktioniert, da wohl in manchen Ausdrücken g[u-7,u-5] - a negativ werden kann, oder zB es bei der Division durch 2 in g[i,u]*(u-i-2)*(u-i+3)/2 nicht ganzzahlige Werte gibt. Das ist für die TBignumber-Arithmetik nicht vorgesehen. Wenn das der Fall ist, brauchst Du doch eine Multipräzisons-Fließkomma-Unit.

PS: Völlig fehlerhaft ist übrigens BMD_StrToBigNum('g[u-5,u]',false), da ja 'g[u-5,u]' überhaupt keine Zahl ist.


jsbach - Di 19.04.11 23:06

danke, ich werde es mal probieren. ich hoffe man verzeiht mir eine solche frage in einem delphi-forum, aber gibt es eine (frei erhältliche) programmiersprache, die von vornherein mit unendlich langen zahlen rechnet?


jaenicke - Mi 20.04.11 05:37

user profile iconjsbach hat folgendes geschrieben Zum zitierten Posting springen:
gibt es eine (frei erhältliche) programmiersprache, die von vornherein mit unendlich langen zahlen rechnet?
Java (java.math.BigInteger), Ruby (bignum), ...


jsbach - Mi 20.04.11 15:51

So, ich habe es jetzt fast geschafft, also mit BigNum zu handtieren. Der Ausdruck g[i,u]*(u-i-2)*(u-i+3)/2 ist immer eine ganze Zahl, doch wie Gammatester bereits angemerkt hat werden die Array-Einträge manchmal negativ. Wenn man das jetzt noch irgendwie umgehen könnte... So funktioniert es jetzt bis u=18.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
const maxi=100;

var
  Form1: TForm1;

  u,i,j,b,k: integer;
  m: extended;
  a,a1,g1,g2,g3,g4,g5: TBignumber;
  Liste: TStringList;
  g: array[-maxi..maxi, -maxi..maxi] of TBignumber;

procedure TForm1.Button1Click(Sender: TObject);
begin

  Liste:=TStringList.Create;

  // alle Arrays auf Null setzen (wichtige Voraussetzung für den Algorithmus)
  j:=-maxi;
  repeat
    i:=-maxi;
    repeat
      g[i,j]:=BMD_StrToBigNum('0',false);
       i:=i+1;
    until i>maxi;
    j:=j+1;
  until j>maxi;

  // u = 6..10 als Startwerte
  g[1,6]:=BMD_StrToBigNum('1',false);  g[2,6]:=BMD_StrToBigNum('1',false);  g[3,6]:=BMD_StrToBigNum('3',false);  g[4,6]:=BMD_StrToBigNum('12',false);
  g[1,7]:=BMD_StrToBigNum('1',false);  g[2,7]:=BMD_StrToBigNum('1',false);  g[3,7]:=BMD_StrToBigNum('2',false);  g[4,7]:=BMD_StrToBigNum('7',false);  g[5,7]:=BMD_StrToBigNum('30',false);
  g[1,8]:=BMD_StrToBigNum('1',false);  g[2,8]:=BMD_StrToBigNum('2',false);  g[3,8]:=BMD_StrToBigNum('2',false);  g[4,8]:=BMD_StrToBigNum('5',false);  g[5,8]:=BMD_StrToBigNum('19',false); g[6,8]:=BMD_StrToBigNum('85',false);
  g[1,9]:=BMD_StrToBigNum('1',false);  g[2,9]:=BMD_StrToBigNum('2',false);  g[3,9]:=BMD_StrToBigNum('3',false);  g[4,9]:=BMD_StrToBigNum('3',false);  g[5,9]:=BMD_StrToBigNum('9',false);  g[6,9]:=BMD_StrToBigNum('37',false);  g[7,9]:=BMD_StrToBigNum('173',false);
  g[1,10]:=BMD_StrToBigNum('1',false); g[2,10]:=BMD_StrToBigNum('3',false); g[3,10]:=BMD_StrToBigNum('5',false); g[4,10]:=BMD_StrToBigNum('7',false); g[5,10]:=BMD_StrToBigNum('7',false); g[6,10]:=BMD_StrToBigNum('23',false); g[7,10]:=BMD_StrToBigNum('99',false); g[8,10]:=BMD_StrToBigNum('476',false);



  u:=11;
  repeat
   m:=floor((u-6)/12);

   k:=5;
      a:=BMD_StrToBigNum('0',false);
      b:=1;
      repeat
        a1:=BM_Multiply(g[u-12*b-5,u-12*b], g[12*b-2,12*b]);
        a:=BM_Add(a, a1);
        b:=b+1;
      until b>m;
      g[u-k,u]:=BM_Sub(g[u-7,u-5], a);
      g[u-k-1,u]:=g[u-k,u];

   k:=6;
      a:=BMD_StrToBigNum('0',false);
      b:=1;
      repeat
        a1:=BM_Multiply(g[u-12*b-5,u-12*b], g[12*b-2,12*b]);
        a:=BM_Add(a, a1);
        b:=b+1;
      until b>m;
      repeat
        g1:=BM_Add(g[u-k,u], a);
        g[u-k-1,u]:=BM_Sub(g1, g[u-8,u-5]);
        k:=k+1;
      until k>8;


   ........ 



i:=1;
    g[u-4,u]:=BMD_StrToBigNum('0',false);
    g[u-3,u]:=BMD_StrToBigNum('0',false);
    g[u-2,u]:=BMD_StrToBigNum('0',false);
    repeat
      g[u-4,u]:=BM_Add(g[u-4,u], g[i,u]);

      j:=u-i-2;
      b:=1;
      g1:=BMD_StrToBigNum('0',false);
      repeat
         g1:=BM_Add(g1, g[i,u]);
         b:=b+1;
      until b>j;
      g[u-3,u]:=BM_Add(g[u-3,u], g1);

      j:=(u-i+3)*(u-i-2)div 2;
      b:=1;
      g1:=BMD_StrToBigNum('0',false);
      repeat
         g1:=BM_Add(g1, g[i,u]);
         b:=b+1;
      until b>j;
      g[u-2,u]:=BM_Add(g[u-2,u], g1);

      i:=i+1;
    until i>u-5;

Ausgabe der Werte


Flamefire - Mi 20.04.11 16:26

Lösung steht oben: Die Klasse verwenden. Die ist von mir für negative Zahlen erweitert und funktioniert damit auch.


Horst_H - Mi 20.04.11 16:48

Hallo,

oder was anderes benutzen ;-)
http://www.polarhome.com:793/~franco/ dort die Unit ARIT-> bigint.zip sehr viel in 32-bit Assembler oder
nx von http://www.ellipsa.eu/public/nx/nx.html was bei mir in der Versoin 0.33 auch unter Delphi 7 PE funktioniert.

Gruß Horst


jsbach - Mi 20.04.11 21:26

Habe Probleme mit BigNum2. Habe wieder alles in meine Unit kopiert, doch es wird bei "TBigNumber = Array Of Byte;" ein ":" statt "=" verlangt??? Ist das Kopieren eigentlich notwendig oder kann man die Unit BigNum2 auch anders aufrufen/benutzen? Habe davon wirklich Null Ahnung.So sieht es jetzt aus. Vorher hat es funktioniert.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
unit MeineUnit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Math,
  StdCtrls;

type
    TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);

// ab hier eingefügt
    TBigNumber = Array Of Byte;

    //Wrapper-Klasse von Sebastian Jänicke - 20.04.2005
    TSJBigNumber = Class
    Private
        fNumber: TBigNumber;
    Public
        Constructor Create(Const Num: TBigNumber); Overload;
        Constructor Create(Const Num: TSJBigNumber); Overload;
        Constructor Create(Const NumString: String; HexInput: Boolean = False); Overload;

  .....
 
  Function BMD_StrToBigNum(Str: String; HexInput: Boolean): TBigNumber;
  Function BMD_BigNumToStr(Num: TBigNumber; HexOutput: Boolean): String;
  Function BMD_FractionToStr(Num1, Num2: TBigNumber): String;

// meine Variablen
const maxi=50;

var
  Form1: TForm1;

  u,i,j,b,k: integer;
  m: extended;
  a,a1,g1,g2,g3,g4,g5: TBignumber;
  Liste: TStringList;
  g: array[-maxi..maxi, -maxi..maxi] of TBignumber;


implementation

// der Rest von BigNum2
Constructor TSJBigNumber.Create(Const Num: TBigNumber);
Begin
    Self.Assign(Num);
End;

Constructor TSJBigNumber.Create(Const Num: TSJBigNumber);
Begin
    Self.Assign(Num.Number);
End;

  .....


jaenicke - Mi 20.04.11 21:40

Du hast die Typdeklarationen mitten in die Deklaration von TForm1 eingefügt... :roll:

Du kannst Typen innerhalb einer type-Sektion nur nacheinander deklarieren, nicht durcheinander. Wie stellst du dir das denn vor? Zuerst muss die Deklaration von TForm1 abgeschlossen sein (oder du schreibst es vor die Deklaration von TForm1).

Du kannst maximal innerhalb von TForm1 unter z.B. public erneut mit type eine neue Typdeklarationssektion eröffnen, aber wozu?

Und warum schreibst du nicht einfach die Unit BigNum2 in die uses? Wozu das Kopieren?


jsbach - Mi 20.04.11 21:59

Auch wenn meine Unwissenheit Unverständnis hervorruft. Ich habe kaum Ahnung davon wie ein Delphi Programm aufgebaut ist oder funktioniert, nur Grundkenntnisse in Pascal. Ich brauche wirklich eine ganz genaue Anleitung (wenns keine Umstände macht). Ich habe nochmal den Programmanfang gepostet. Wenn ich "BigNum2" in uses einfüge gibt es die Fehlermeldung: Datei nicht gefunden: 'BigNum2.dcu'. BigNum2 ist derweil in einer weiteren Registerkarte.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
unit MeineUnit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Math, StdCtrls;

type
    TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;


const maxi=50;

var
  Form1: TForm1;

  u,i,j,b,k: integer;
  m: extended;
  a,a1,g1,g2,g3,g4,g5: TBignumber;
  Liste: TStringList;
  g: array[-maxi..maxi, -maxi..maxi] of TBignumber;


implementation
{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
begin
...usw


jaenicke - Mi 20.04.11 23:03

user profile iconjsbach hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich "BigNum2" in uses einfüge gibt es die Fehlermeldung: Datei nicht gefunden: 'BigNum2.dcu'.
Hast du denn die Datei BigNum2.pas im selben Verzeichnis liegen?


jsbach - Mi 20.04.11 23:32

Ich will mich natürlich auch selbst bemühen... Mit Hilfe der Delphi-Hilfe ist BigNum2 jetzt unter uses eingebunden. Programm läuft wieder. Jetzt fehlt mir noch das Verstöndnis für "... immer erst eine Instanz anlegen (mit TSJBigNum.Create)..." Was bedeutet das, wo schreibe ich das hin?


jaenicke - Mi 20.04.11 23:36

Hier z.B. findest du Informationen über Klassen und Objekte:
http://www.delphi-treff.de/object-pascal/klassen-und-objekte/


jsbach - Do 21.04.11 13:11

Also, so habe ich es jetzt verstanden, aber offenbar falsch. Ich brauche WIRKLICH ganz konkrete Hilfe per Klartext.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
unit MeineUnit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Math, BigNum2, StdCtrls;

type
    TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;


const maxi=100;

var
  Form1: TForm1;

  u,i,j,b,k: integer;
  m: extended;
  a,a1,g1,g2,g3,g4,g5: TSJBigNumber;
  Liste: TStringList;
  g: array[-maxi..maxi, -maxi..maxi] of TSJBigNumber;


implementation
{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
begin

  Liste:=TStringList.Create;

  // alle Arrays auf Null setzen
  j:=-maxi;
  repeat
    i:=-maxi;
    repeat
      g[i,j]:=TSJBigNumber.Create;     
      g[i,j]:=BMD_StrToBigNum('0',false);  // Fehlermeldung: Inkompatible Typen: 'TSJBigNumber' und 'TBigNumber'
      i:=i+1;
    until i>maxi;
    j:=j+1;
  until j>maxi;


jaenicke - Do 21.04.11 14:35

user profile iconjsbach hat folgendes geschrieben Zum zitierten Posting springen:
Also, so habe ich es jetzt verstanden, aber offenbar falsch. Ich brauche WIRKLICH ganz konkrete Hilfe per Klartext.
:roll:
user profile iconjsbach hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
      g[i,j]:=TSJBigNumber.Create;     
      g[i,j]:=BMD_StrToBigNum('0',false);  // Fehlermeldung: Inkompatible Typen: 'TSJBigNumber' und 'TBigNumber'
Du kannst das nicht so mischen (und wozu auch?). Entweder TSJBigNumber oder die einzelnen Funktionen, aber nicht beides, du musst dich schon entscheiden...

Delphi-Quelltext
1:
      g[i, j] := TSJBigNumber.Create('0', false);                    


jsbach - Do 21.04.11 14:59

ganz ehrlich, da wär ich nie drauf gekommen. danke!


jsbach - Do 21.04.11 15:40

leider geht es nur tröpfenweise voran, jetzt hakte es bei den funktionen. so geht es wohl nicht:

Delphi-Quelltext
1:
2:
a1:=TSJBigNumber.Multiply(g[u-12*b-5,u-12*b], g[12*b-2,12*b]);
a:=TSJBigNumber.Add(a, a1);


jaenicke - Do 21.04.11 15:59

user profile iconjsbach hat folgendes geschrieben Zum zitierten Posting springen:
leider geht es nur tröpfenweise voran, jetzt hakte es bei den funktionen. so geht es wohl nicht:
Nein, denn das sind keine Klassenfunktionen... absolute Grundlagen...

Delphi-Quelltext
1:
a1 := g[u-12*b-5,u-12*b].Multiply(g[12*b-2,12*b]);                    


jsbach - Do 21.04.11 20:58

Das ergibt bei mir folgende Fehlermeldung:
Inkompatible Typen: 'TSJBigNumber' und 'procedure, untyped pointer or untyped parameter'.


jsbach - Fr 22.04.11 14:40

ok, das letzte problem habe ich selbst lösen können. sind jetzt halt andere befehle, sum statt add, usw.
jetzt fehlt mir nunr noch die neue ausgabe. bei bignum_lib war es ja: BMD_BigNumToStr(g[16,18],false), doch jetzt bei bignum2? ich probiere jetzt seit zwei stunden rum und kriege es einfach nicht hin...


jaenicke - Fr 22.04.11 14:53

Naja, also so viele Methoden hat die Klasse ja eigentlich nicht...

Aber selbst wenn du die Bedeutung von AsString nicht von alleine erkennst:
Wenn du einmal in der Unit nach BMD_BigNumToStr, das du ja kennst, gesucht hättest, hättest du gesehen, dass diese Funktion in der Klasse nur einmal verwendet wird:

Delphi-Quelltext
1:
2:
3:
4:
Function TSJBigNumber.AsString(HexOutput: Boolean): String;
Begin
    Result := BMD_BigNumToStr(Self.fNumber, HexOutput);
End;
Du musst also hier nur AsString benutzen.


jsbach - Fr 22.04.11 15:10

also z.b.: showmessage(g[15,17].AsString); ...juchu, es klappt!