Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi wirklich große Zahlen unter Delphi (https://www.delphipraxis.net/75188-wirklich-grosse-zahlen-unter-delphi.html)

Antigo 15. Aug 2006 16:42


wirklich große Zahlen unter Delphi
 
Hi,
aus langeweile und Interesse habe ich mir ein Faktorisierungsprogramm geschrieben. Das ist nichts tolles, das weiss ich, aber ich würde mein Programm trotzdem mal gerne an wirklich großen Zahlen versuchen lassen. Und mit groß meine ich erstmal Zahlen mit einer zweistelligen Anzahl an Ziffern.

Ich weiss das es sowas wie Int64 gibt. Aber erstens würde das (wenn ich das richtig verstehe) auch "nur" (:D) Zahlen bis 2^64 zulassen. Und da wäre dann ja auch bei 19 Stellen schluss.
Und zweitens weiss ich nicht wie ich damit arbeite. Kann ich einfach überall statt >Integer< >Int64< schreiben?

Und wie gehts danach weiter? WIe kann ich mit noch größeren Zahlen arbeeiten?


Vielen Dank schonmal im vorraus :)

3_of_8 15. Aug 2006 16:50

Re: wirklich große Zahlen unter Delphi
 
Fast.

Wenn du wirklich große Zahlen suchst, nimm Extended. Das Teil kann sehr große Zahlen verarbeiten, allerdings dann nur noch auf maximal 20 Stellen genau, dafür jedoch fast beliebig groß.

Und etwas langsamer.

Ansonsten geht Int64 genauso wie Integer, nur ist es kein Ordinaltyp, das heißt du kannst sie nicht für Schleifen verwenden.

EDIT: Wenn dus noch größer brauchst, verwende die DECMath von Hagen.

Antigo 15. Aug 2006 17:00

Re: wirklich große Zahlen unter Delphi
 
das problem ist, dass ich zur Faktorisierung die Funktion >mod< unbedingt brauche. Und die funktioniert halt nur mit Integer Werten. Ansonsten müsste ich mir wohl irgendwas selbst basteln und die FUnktionen wie modulo selbst nachprogrammieren, was aber eigentlich für ein Spass programm etwas viel wäre.

Ich werd dann mal nach dieser DECMath Unit suchen. Vielen Dank :)

3_of_8 15. Aug 2006 17:14

Re: wirklich große Zahlen unter Delphi
 
[delphi]
function fmod(a, b: Extended): Extended;
begin
result:=a-(a/b);
end;

CalganX 15. Aug 2006 17:57

Re: wirklich große Zahlen unter Delphi
 
@3_of_8:
Extended < Int64

Abgesehen davon verwendet Extended Nachkommastellen und belegt dadurch schon Speicher. Bei einem Faktorisierungsprogramm braucht man aber keine Nachkommastellen.

Chris

Alexander Roth 15. Aug 2006 18:03

Re: wirklich große Zahlen unter Delphi
 
Zitat:

Zitat von 3_of_8
EDIT: Wenn dus noch größer brauchst, verwende die DECMath von Hagen.

Wie er es anscheinend bracht.

DEC kann ich nur empfehlen. Habe ich selbst bei einem meiner Matheprpgramme benutzt (siehe: Primfaktoren)

Schu mal auf Luckies Homepage. Da findest du die aktuelle DEC Version. Manches davon sogar Open Source!

Der_Unwissende 15. Aug 2006 18:07

Re: wirklich große Zahlen unter Delphi
 
Zitat:

Zitat von 3_of_8
Delphi-Quellcode:
function fmod(a, b: Extended): Extended;
begin
result:=a-(a/b);
end;

Dumme Frage, was genau soll denn fmod machen? Das hat doch nichts mit modulo zu tun, oder seh ich das gerade völlig falsch? Wenn ich mit der Formel z.B. 10 mod 5 rechne, würde ich als Ergebnis 10 - (10 / 2) = 8 bekommen, hm, wäre ich nicht glücklich!

Gruß Der Unwissende

3_of_8 15. Aug 2006 18:14

Re: wirklich große Zahlen unter Delphi
 
Ups, da hast du recht. Hab ich Mist gebaut.

Delphi-Quellcode:
function fmod(a, b: Extended): Extended;
begin
result:=a-Extended(trunc(a/b))*b;
end;
@Chakotay: Ein Gleitkommawert ist AFAIK so aufgebaut, dass er eine Zahl sowie ihren 10er Exponenten speichert. Das heißt praktisch, ich nehme die Zahl 42 und lasse ihr Komma mal um 30 stellen nach rechts "gleiten" und habe dann 42*10^30, was man nicht mit nem Integer darstellen kann. ;)

CalganX 15. Aug 2006 18:24

Re: wirklich große Zahlen unter Delphi
 
Zitat:

Zitat von 3_of_8
@Chakotay: Ein Gleitkommawert ist AFAIK so aufgebaut, dass er eine Zahl sowie ihren 10er Exponenten speichert. Das heißt praktisch, ich nehme die Zahl 42 und lasse ihr Komma mal um 30 stellen nach rechts "gleiten" und habe dann 42*10^30, was man nicht mit nem Integer darstellen kann. ;)

Nein. Extended speichert die Daten nach IEEE754. D.h. es wird wenn überhaupt der Exponent zur Basis 2 gespeichert. Und sofern Extended unter Delphi nicht 64Bit belegt, wird Extended nicht an Int64 rankommen - und soweit ich weiß ist das der Fall. ;)

Chris

Der_Unwissende 15. Aug 2006 18:32

Re: wirklich große Zahlen unter Delphi
 
Zitat:

Zitat von Chakotay1308
D.h. es wird wenn überhaupt der Exponent zur Basis 2 gespeichert.

Was heißt denn hier wenn überhaupt? Natürlich wird ein Exponent abgespeichert! Wie soll denn bitte eine Gleitkommazahl ohne berechnet werden?

Zitat:

Zitat von Chakotay1308
Und sofern Extended unter Delphi nicht 64Bit belegt, wird Extended nicht an Int64 rankommen - und soweit ich weiß ist das der Fall. ;)

Wo kommt denn jetzt dieses Wissen her? Hilfe! Ich meine schau in die Delphi Hilfe, da steht dass Extended 10 Byte verwendet, 10 Byte = 80 Bit > 64 Bit. Dann kannst du gleich deine eigene Quelle bemühen, da steht:
Extended = 64 Bit Mantisse und 15 Bit Exponent (1 VZ Bit).

Eine Gleitkommazahl (genauer ihr Betrag) berechnet sich nun aus Mantisse * Basis (hier fest 2)^Exponent. Natürlich ist ein Extended hier also größer als ein Int64 Wert. Der Größte Extended Wert liegt bei 1.1 * 10^4932! Das ist ordentlich groß!

CalganX 15. Aug 2006 18:38

Re: wirklich große Zahlen unter Delphi
 
Zitat:

Zitat von Der_Unwissende
Was heißt denn hier wenn überhaupt? Natürlich wird ein Exponent abgespeichert! Wie soll denn bitte eine Gleitkommazahl ohne berechnet werden?

Ungünstig formuliert, stimmt...

Zitat:

Wo kommt denn jetzt dieses Wissen her? Hilfe! Ich meine schau in die Delphi Hilfe, da steht dass Extended 10 Byte verwendet, 10 Byte = 80 Bit > 64 Bit.
Ich habe kein Delphi installiert und somit auch keine Delphi-Hilfe, auf die ich auf die Schnelle zugreifen könnte. Aber wenn das dort so steht, dann habe ich mich falsch erinnert. Errare humanum est. ;)

Zitat:

Dann kannst du gleich deine eigene Quelle bemühen, da steht:
Extended = 64 Bit Mantisse und 15 Bit Exponent (1 VZ Bit).
Ich war mir nicht sicher, ob die Angaben dort mit Delphi übereinstimmen...

Chris

r2c2 15. Aug 2006 18:51

Re: wirklich große Zahlen unter Delphi
 
Zitat:

Zitat von 3_of_8
Wenn du wirklich große Zahlen suchst, nimm Extended. Das Teil kann sehr große Zahlen verarbeiten, allerdings dann nur noch auf maximal 20 Stellen genau, dafür jedoch fast beliebig groß.

Beliebig groß nicht. Maximal 2^80(25 Stellen). Da Extended ein Float is, eigenet sich das Viech wohl eher weniger für die Faktorisierung...

Zitat:

Ansonsten geht Int64 genauso wie Integer, nur ist es kein Ordinaltyp, das heißt du kannst sie nicht für Schleifen verwenden.
Seit wann das? :gruebel: *grad nochmal nachguckt* Ui...jo...hast Recht...

Zitat:

EDIT: Wenn dus noch größer brauchst, verwende die DECMath von Hagen.
Wollt auch grad sagen. Es gibt u.a. von Hagen Lösungen für dieses Problem. Wie das dann allerdings mit der Performance aussieht, weiß ich nicht. Wobei ich Hagen zutraue alle Register zu ziehen und das ganze auch sehr performant hinzukriegen...

//Edit:
Ah.... Hilfeee.... So langsam war ich auch noch nicht. Der Post um 17:50 Uhr war der letzte den ich gesehen hab... 2h zu spät.... ich werd alt... kommt davon, wenn man zwischendurch was anderes macht(essen...) und später antworten will... Und der rote Kasten hat mich noch nichtmal gewarnt... *heul* Ich will den roten Kasten wieder haben *quängel* Hoffentlich beeilt sich Cheffe mit der DP 2006... *schluchtz* :cry:

mfg

Christian

3_of_8 15. Aug 2006 18:55

Re: wirklich große Zahlen unter Delphi
 
Hehe, gibts irgendwas was die DEC respektive Hagen nicht kann? :mrgreen:

Und wenn, dann auch noch schnell.

Also ich konnte mich eigentlich nicht beschweren, als mir Hagens DEC Math in 10 Sekunden ein paar Millionen Nachkommastellen der Quadratwurzel von 2 geliefert hat. :D

Antigo 15. Aug 2006 18:57

Re: wirklich große Zahlen unter Delphi
 
danke für soviele antworten :)


Dieses Decmath scheint vielversprechend. Jetzt muss ich das nurnoch in mein Programm einbauen ^^
Gibt es irgendwo eine Dokumentation für alle Funktionen der Unit NInts? Das fände ich ziemlich hilfreich, denn ohne weiss ich noch nichtmal wie ich überhaupt eine Variable des typs IInteger erzeuge...


jetzt werde ich wohl auch von for auf while schleifen umsteigen müssen...

Antigo 15. Aug 2006 19:20

Re: wirklich große Zahlen unter Delphi
 
Ich habe jetzt ein Array von IInteger Werten, in dem ich meine Primzahlen speichern möchte. Ich hab eine Funktion die mir die "nte" Primzahl geben soll. Die guckt nach ob die geforderte Primzahl schon im Array steht, wenn nicht dann wird sie errechnet. Dabei mache ich (bisher) folgendes:
Delphi-Quellcode:
 if length(primzahlen)-1 >= n then begin
  //wenn Primzahl bereits errechnet, dann ausgeben
    result:=primzahlen[n];
  end
  else begin
Jetzt ist n aber auch eine IInteger Zahl. length(primzahlen)-1 hingegen ist eine Integer Zahl. Wie vergleiche ich die beiden miteinander? Und bekomme ich nachher Probleme weil mein Array zu groß wird?

negaH 15. Aug 2006 20:13

Re: wirklich große Zahlen unter Delphi
 
Hi

Da will ich mich mal nicht lumpen lassen und einige zusätzliche Infos rüberwachsen lassen.

1.) im Ordner \Intf\ des ZIPs findest du alle Interfaces der Units aus dem DECMath. In der Datei NInts.pas findest du dann auch alle Funktionen samt Remarks dazu.

2.) DECMath enthält schon ein Objekt TSmallPrimeSieve in Unit Prime.pas. Mit diesem Sieb hats du sehr schnell alle Primzahlen zwischen 2 bis 2^32-1 zur Verfügung.

Beispiel für die Benutzung
Delphi-Quellcode:
var
  I,P: Cardinal;
begin
// Ausgabe der 100'ten bis 1000'ten Primzahl
  for I := 100 to 1000 do
    WriteLn( Primes[I] );

// suche Index der Primzahl 13
  WriteLn( Primes.IndexOf(13) )

// Überprüfung ob Cardinal eine Primzahl ist
  if IsPrime(123456789) then

end;
3.) diese Primzahlsieb wird nun in einigen Faktorizations Funktionen der IInteger benutzt

Beispiel

Delphi-Quellcode:
var
  N: IInteger;
  F: Cardinal;
begin
  NRnd(N, 128); // 128 Bit großen Integer erzeugen

  repeat
    F := NSmallFactor(N);
    if F > 1 then
    begin
      WriteLn(F);
      NDiv(N, F); // N := N / F;
    end;
  until F <= 1;

  WriteLn(NStr(N)); // N ausgeben

  if NIsProbablePrime(N) then WriteLn('is prime)
    else WriteLn('is composite');
end;


function NSmallFactor(const A: IInteger; Bound: Cardinal): Cardinal;
// Result == 0 if A = 0
// Result == 1 if A is not divisible by all primes <= bound or
//             if A is < 2^32 if A is prime
// Result >= 2 small prime divisor
// about <10000 Cycles per digit and Bound = $FFFF and A >= 2^960
// 2.6 times faster as with the use of normal NMod() operation
// about <96 Cycles per digit and Bound = 239 and A >= 2^960
// the growrate isn't linear, bigger A are faster tested per digit
NSmallFactor(N) ermittelt ob eine Zahl N durch eine Primzahl bis < 2^32 teilbar ist. Wenn ja gibt NSmallFactor() diesen Faktor zurück. Dabei arbeitet diese Funktion mit hocheffizienten Verfahren die die modulare Division -> mod -> die normalerweise notwendig wäre ersetzt. Damit dürfte diese Funktion weitaus schneller sein als jeder normale TrialDivisons Ansatz. Gearbeitet wird in dieser Funktion mit einer Multiplikation zum moduarem Inversen der kleinen Primzahlen bis 2^32. Im Bereich bis 2^16 werden zb. durch ein einzigste dieser Multiplikation gleich 2 Primzahlen abgetestet. Ein weitere sehr performanter Test der als erstes durchgeführt wird wird mit einer Addition modulo 2^96-1 gearbeitet. Dieser Test reduziert die Zahl N modulo 2^96-1, was mit reinen Additionen durchführbar ist. Das Resultat (96 Bits Zahl) wird nun mit einer speziellen modularen DIvision ausgewertet und kann in einem Rutsch gleich 12 der kleinen Primzahlen austesten.

NTrialDivision(N) testet N ob es durch ein der kleinen Primzahlen geteilt werden kann. Diese Funktion liefert nur die Antwort ob die Zahl N "teilbar" oder "nicht teilbar" ist.

NIsProbablePrime(N) ist nun ein Pseudo Primzahl Test, so was ähnliches wie das Rabin Miller Verfahren. Damit kann man also jede beliebige Zahl auf Primzahl testen. Die Wahscheinlichkeit das diese Zahl dann auch eine Primzahl ist beträgt 1/N wobei N unser zu testende Zahl ist. Wenn du also zb. ein 512 Bit große Zahl damit testest dann ist die Wahrscheinlichkeit das sie denoch keine Primzahl ist obwohl der Test es meint nur 1/2^512 gruß, also fast unendlich klein. Deshalb nennt man solche getesteten Zahlen auch "industrielle Primzahlen". Nun, NIsProbablePrime() benutzt ein sehr sehr modernes Verfahren, das wesentlich schneller und auch sicherer ist als ein Rabin Miller Test. Das Verfahren das benutzt wird ist ein "Strong Probable Lucas Prime Test" nach "Pomerance, Selfridge, Wagstaff und Bailie". Zusätzlich testet dieses Verfahren auch noch ob N ein perfektes Quadrat ist -> N = X^2.

NIsProbablePrime() ist eine Allround Funktion, d.h. sie benutzt verschiedene Testverfahren um dann ein gutes ergebnis zu liefern. Als erstes eine Trial Divison mit NTrialDivison() und danach den SPP Test -> NSPP().

NSPP(N, array of Primes) -> Example: if NSPP(N, [2,3,5,7]) then

testet mit einem Strong Pseudo Primality Algorithmus die Zahl N. Dabei wird im Array [] die Zahlen angegeben zu denen getestet werden wollen (fast immer Primzahlen). Normalerweise reicht der Auffruf NSPP(N, [1, 2]) aber aus. In diesem Moment wird mit dem moderneren Bailie-Pomerance-Selfridge-Wagstaff-Test gearbeitet.


NMakePrime() erzeugt eine industrielle Primzahl

Delphi-Quellcode:
var
  P: IInteger;
begin
  NRnd(P, 512); // P zufällige Zahl mit 512 Bit Größe erzeugen

  NMakePrime(P, [1,2]); // erzeuge eine starke Pseudo Primzahl

  WriteLn( NStr(P) );
end;

So, das als grundsätzliches Handwerkszeug. Interessant sind auch noch die Lucas Funktionen -> NLucasMod() usw.

Aber das ist leider nur der Anfang. Auch deine Methode per Trial Divisionen mit den kleinen Primzahlen zu arbeiten ist wirklich nur der Anfang. Solche Verfahren sind die von der Komplexität her gesehen schlechtesten die es gibt. Dh. bei zahl größer 2^64 wird es weitaus besser Verfahren geben als die Trial Divison. Zb. Faktiorsation mit dem Zahlensieb (das bisher beste Verfahren), es arbeitet mit hoch komplexer Mathematik und sehr oft in Elliptischen Kurven (auch da enthält DECMath in den Units GFPs.pas zb. alles was man für Elliptische Kurven in GF(p) benötigt). Oder die Methoden nach Rabin, Williams+1, Pollard Rho, Pollard PP+1 usw.
Das sind alles Verfahren die weitaus effizienter Zahlen faktorisieren können.


Gruß Hagen

Antigo 15. Aug 2006 20:31

Re: wirklich große Zahlen unter Delphi
 
danke für die ausführliche Antwort, die wird sicher auch vielen anderen weiterhelfen :)

Es ist mir klar das die Trial and Error Methode die ich implementiert habe bei weitem nicht effizient ist. Das war aber auch gar nicht mein Ziel. Genauso wenig ist es aber mein Ziel eine Methode zu implementieren die ein anderer geschrieben hat, und die ich (im Moment zumindest ;))nicht mal im Ansatz verstehe ;)


Ich wollte auch eigentlich nur mein Programm an größeren Zahlen testen. Mit deinen IIntegers zu arbeiten ist dabei aber für mich leider nicht ideal. Ich muss dafür viel zu viel umwerfen. ich kann nicht einfach schreiben if i < round(sqrt(zahl)) sondern muss dafür ewig viele Schritte machen (zumindest nach meinem jetzigen Kenntisstand und nachdem was ich bisher rausgekriegt habe ;))

Ich hatte mir eigentlich einen Datentyp erhofft den ich einfach mit dem Standard Integer vertausche und fertig. Leider scheint das nicht so einfach zu sein (was ich irgendwo nicht verstehe) wie ich dachte.
Von daher werd ich mein Programm wohl so belassen.

Trotzdem vielen Dank für eure Mühe :)

negaH 15. Aug 2006 20:52

Re: wirklich große Zahlen unter Delphi
 
Zitat:

Gibt es irgendwo eine Dokumentation für alle Funktionen der Unit NInts? Das fände ich ziemlich hilfreich, denn ohne weiss ich noch nichtmal wie ich überhaupt eine Variable des typs IInteger erzeuge...

Nach dem Entpacken hast du 2 Möglichkeiten:

1.) im Ordner \LibIntf\ sind alle PASCAL Header der Units enthalten. Da kannst du nachschlagen.
2.) im Ordner \Part_II\Demo\ findest du ein DEMO Projekt. In diesem wird die Benutzung der IInteger demonstriert

Ein IInteger ist wie ein normaler Integer anzusehen nur mit dem Unterschied
a.) das er so groß wir der gesamte Speicher sein könnte (als Zahl wohl gemerkt)
b.) er mit eigenen Funktionen rechnen muß (in Unit NInts)

ansonsten gibts fast keine Unterschiede, besonders nicht bei Zuweisungen, Allokation und Freigeben. Darum musst du dsich nicht kümmern und DECMath macht das alles automatisch für dich.

Beispiel

Delphi-Quellcode:
procedure DEMO;
var
  Sum: IInteger;

  function DoTest(const N: IInteger): Boolean; register;
  begin
    NAdd(Sum, N);
    Result := False;
  end;

var
  A,B,C: IInteger;
  X: IIntegerArray;
begin
  // A,B,C sind hier schon auf NIL initialisiert. NIL ist per Definition im DECMath identisch zum Zahlenwert 0 !!

  NSet(A, 12); // A := 12;
  NSet(B, A);  // B := A; // @B == @A, B und A sind gleiches Speicherobjekt
  C := B;      // C := B := A;

  NAdd(B, C);  // B := B + C;
 
  SetLength(X, 3);
  X[0] := A;
  X[1] := B;
  X[2] := C;
 
  NForEach(X, @DoTest); // für jedes Element eine Callback -> DoTest aufrufen.
                        // Diese Callback kann auf unsere Variablen im Stack zugreifen, hier Sum !!
     

  WriteLn( NStr(Sum) ); // ergibt Sum := A + B + C;
end;
Wie du siehst, nichts freigeben, nichts allozieren, alles wird autom. gemacht.

Zitat:

if i < round(sqrt(zahl)) then
Delphi-Quellcode:
var
  T: IInteger;
begin
  NSqrt(T, Zahl); // T := Zahl^0.5
  if NCmp(NInt(I), T) < 0 then ;
end;
1.) NSqrt(T, Zahl), berechne Quadratwurzel der Zahl und speichert das Resultat in T
2.) NInt(I), wandelt I in einen IInteger um
3.) NCmp(NInt(I), T) vergleich I mit T und gibt < 0 zurück wenn I < T, = 0 wenn I == T und > 0 wenn I > T.

Also nur 1 Variable und 1 Zeile Source mehr ;)

Gruß Hagen

Shaman 15. Aug 2006 21:40

Re: wirklich große Zahlen unter Delphi
 
Hey there

Ich spiele mit dem Gedanken, eine Unit für komplexe Zahlen zu schreiben und dafür ebenfalls Interfaces zu verwenden...
Wie siehts aus bezüglich Overhead? Also wenn man ganze Matrizen voll mit solchen Interfaced Numbers verwendet...

Gruss
Shaman

Antigo 15. Aug 2006 21:53

Re: wirklich große Zahlen unter Delphi
 
Zitat:

Also nur 1 Variable und 1 Zeile Source mehr
jo in diesem speziellen Falle. Allerdings muss ich an vielen Stellen eine Variable und eine Zeile COde mehr hinschreiben ;)

Aber jetzt bin ich auf jeden fall schonmal schlauer. NCmp(a,b) gibt -1 aus wenn a <b. 0 wenn a=b und 1 wenn a>b ist. Damit komme ich schonmal weiter.


Vielen Dank nochmal :)

negaH 15. Aug 2006 22:43

Re: wirklich große Zahlen unter Delphi
 
Zitat:

Ich spiele mit dem Gedanken, eine Unit für komplexe Zahlen zu schreiben und dafür ebenfalls Interfaces zu verwenden...
Wie siehts aus bezüglich Overhead? Also wenn man ganze Matrizen voll mit solchen Interfaced Numbers verwendet...


Gute Frage, die ich mir damals auch gestellt habe ;) Und jetzt weis ich die Antwort ganz genau.

Also im normalen Tagesgeschäft, rechnen mit sehr großen Zahlen, ist der Overhead minimal. Es ist sogar so, das ich NUR über die Interfaces auf einfachste Weise einen Speichermanager reinbauen konnte. Dieser ist optimiert auf die Bibliothek und bingt nun ca. 10% größerer Performance. Das heist die Interfaces beschleunigen sogar, weil mit ihnen mehr Features möglich sind ;)

Wenn man aber 32-64Bit Rechnungen durchführt so wird dies meist langsammer sein als mit Int64 oder so. Das muß aber nicht immer so sein, zb. bestimmte Spezial-Algorithmen die in den IInteger enthalten sind wurden in mehere Implementierungen aufgeteilt. Dabei wird je nach Zahlengröße ein andere Algo. benutzt. Dieser Algo. ist dann spezialisiert auf Zahlen odedr Berechnungen m,it bestimmten Schranken. Das ist sehr oft der Fall. Nun, im DECMath sind einige 32-64 Bit Algortihmen drinnen die schneller sind als die RTL.

Bei den Interfaces gibts noch eines anzumerken. Ich bezeichne meine IInteger als "forged Interfaces", weil sie in ihrer Implementierung nicht auf TObject/TINterfacedObject basieren. Meine Interfaces sind stinknormal Records und die wichtigsten Interface Funktionen sind in ASM optimiert (Allozierung, FIFO Stack, Calculation Management).

Interfaces mit TInterfacedObject Implementierungen sind in ihren Aufrufkonventionen von Methoden ziemlich ineffizient.

In kurz: der Impakt der Interfaces ist sehr gering auf die Performance aber je nach Sprache und Funktionalität des Compilers eine weitreichende Entscheidung -> im DECMath eben Prozedurales Konzept mit überladenen Funktionen, sehr kurzen Funktionsnamen und sehr strikter Parametersignatur der Funktionen.


Gruß Hagen

Antigo 16. Aug 2006 17:00

Re: wirklich große Zahlen unter Delphi
 
Also eine Frage hätt ich noch ;)
Ich möchte eine große Zahl einlesen, dafür mache ich folgendes:

Delphi-Quellcode:
 
  NSet(a,edit1.Text);
  Showmessage(NStr(a));
Allerdings werden die Zahlen dann in 5er Päckchen ausgegeben. Ist das so gewollt?

negaH 16. Aug 2006 19:34

Re: wirklich große Zahlen unter Delphi
 
Ja, da man so sehr einfach in 5er Schritten die Anzahl der Stellen der Zahl abzählen kann.

Du kannst dasaber abändern wie du es wünscht ;)

NStr() kann die Binärzahl, interne Darstelung, in insgesamt 63 verschiedene Zahlenbasen umwandeln. Alle Basen von 2 bis 64 und 256 sind möglich. Du kannst die IInteger also mit NStr() zb. zur basis 10 = Dezimal umwandeln, oder Oktal = Basis 8 oder Trinär Basis 3 usw. usw.

Beispiel:

Delphi-Quellcode:
var
  S: TStrFormat;
begin
  NStr(N); // umwandeln nach Default Format gespeichert in der globalen Struktur NStrFormat in Unit NInts.pas

  NStr(N, 2) // umwandeln zu einem Binärzahlenstring
  NStr(N, 16) // umwandeln in einen Hexadezimalen String

  S := NStrFormat;
  S.Base := 10;
  S.Plus := '+';
  S.Minus := '-';
  S.Zero := '0';
  S.DigitsPerBlock := 10; // 10 Ziffern als Block
  S.BlockSep := '-#-'; // die Zeichen -#- zwischen den 10'er Blöcken

  NStr(N, S); // umwandeln in unser eigenes Stringformat
end;

Type
  TStrFormat = packed record          // String-Convertion structure
    Base: TBase;                      // Numberbase
    Plus: array[0..15] of Char;       // String for positive IInteger (+)
    Minus: array[0..15] of Char;      // String for negative IInteger (-)
    Zero: array[0..15] of Char;       // String for zero             (0)
    Comma: Char;
    DigitsPerBlock: Word;             // Digits on one Block
    BlockSep: array[0..15] of Char;   // separator between two blocks (Space)
    BlockPadding: Char;               // left padding char of first block
    DigitsPerLine: Word;              // count of digits in one line
    LineSep: array[0..15] of Char;    // separator after one line (CR+LF)
    LinePadding: Char;                // left padding char of first line
    DigitsChars: array[0..63] of Char; // possible Digits of a valid Numberstring
    FormatChars: array[0..63] of Char; // Numberstrings can contain these chars, but should be ignored
    LeftAlign: Boolean;
    Offset: Integer;                  // Offset to first char that contains digits, NSet(string)
    Precision: Integer;
  end;

var
  NStrFormat: TStrFormat = (
    Base: 10;
    Plus: '';
    Minus: '-';
    Zero: '';
    Comma: ',';
    DigitsPerBlock: 5;
    BlockSep: ' ';
    BlockPadding: ' ';
    DigitsPerLine: 0;
    LineSep: #13#10;
    LinePadding: #0;
    DigitsChars: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/';
    FormatChars: ' /\-+;:#~"()[]?_<>!§$%&{}'''#13#10#9;
    LeftAlign: False;
    Offset: 0;
    Precision: 0;
   );

function NStr(const A: IInteger; Base: TBase = 0): String; overload;
function NStr(const A: IInteger; const Format: TStrFormat): String; overload;
Oben mal die Typdeklaration von TStrFormat und die globale Variable NStrFormat die als Default benutzt wird.

Gruß Hagen

Antigo 16. Aug 2006 21:40

Re: wirklich große Zahlen unter Delphi
 
unfassbar was da alles schon vorgefertigt ist. Da braucht man ja nix mehr selber zu machen ^^

Vielen Dank wiedermal ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:02 Uhr.

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