|
Antwort |
Registriert seit: 25. Jun 2003 Ort: Thüringen 2.950 Beiträge |
#51
Hi
Mehrere Optimierungsmöglichkeiten fallen mir da ein. 1.) es gibt bessere Typen des verwendeten Chudnovsky Algorithmus, sprich höherdimensionale Formeln. Statt 15 Stellen auf einmal zu berechnen können diese Chudnovsky Formeln z.B. 31 Stellen auf einmal berechnen. Allerdings sind diese Formeln viel komplizierter als die von mir benutzte 2.) die benutzte Formel basiert in weiten Teilen auf dem sogenannten "Binary Splitting". Man kann sich das so vorstellen das das Ziel eine Zahl X mit Y Stellen ist. Nun zerlegt man diese Y Stellen in zwei Teile einen Linken und Rechten Teil. Man versucht nun eine Formel zu finden die den Linken und Rechten Teil separat berechnen kann und dann nur noch den Linken und Rechten Teil miteinander multipliziert. Somit haben wir zwei kleine Berechnungen mit halb so großen Zahlen und deren Resultate werden multipliziert. Man kann nun Rekursiv wiederum den Linken und Rechten Teil teilen, usw. usw. Somit reduziert man die Zahlengrößen in den Berechnungen immer weiter. Wichtig ist es dabei das die beiden Zahlen der Linken und Rechten Seite der Berechnung möglichst gleichgroß sind. Denn dadurch wird der maximale Durchsatz, eg. Geschwindigkeit der Berechnungen erzielt. Es ist nämlich so das man zwei gleichgroße Zahlen am schnellsten Multiplizieren kann, d.h. zB. zwei Zahlen bei denen die eine Zahl 2 mal so lange wie die andere ist, wird immer langsammer pro Bit sein als wenn die beiden Zahlen etwa gleichgroß sind. Nun, exakt hier könnte man ebenfalls ansetzen, denn die von mir benutze Formel zur Pi Berechnung erzeugt NICHT immer gute Rechte + Linke Zahlen. Ziel der Optimierung ist es also die Berechnungen besser auszugleichen. 3.) Der von mir benutzte Binary Splitting Algorithmus ist ein Algo der auf Universalität codiert wurde. Im Falle der Pi Berechnung schleppt dieser Algo. z.B. eine Variable zusätzlich sinnlos mit. Das kostet Zeit. Ziel der Optimierung wäre es also einen eigenen Binary Splitting Algo. zu coden der besser auf die Anforderungen der Pi Formel angepasst ist. Unten habe ich mal den derzeitigen Bin. Splitting Algo. gepostet. 4.) Die Bin. Splitting Callback der Pi Berechnung berechnet viele succzessive Variablen. Im Grunde sind diese voneinander abhängig in ihren Zahlenwerten. Aber! meine Callback berechnet diese Werte immer absolut. Ziel der Optimierung wäre es nun diese Zahlenwerte ebenfalls inkrementell zu erzeugen, sprich die vielen kleinen Multiplikationen durch schnellere inkrementelle Additionen zu ersetzen. Dies ist durchaus möglich, man muß nur die besten Formeln dafür finden. 5.) meine Math. Library nutzt ganz verschiedene Multiplikations-verfahren abhänig von den Zahlengrößen. Für die längst-andauerenen Berechnungen = größten Zahlen wird der asymptotisch schnellste Algorithmus der heutzutage bekannt ist verwendet. Es ist die Modulare Fermat Fast Fourier Transformation von Schönhage und Strassen. Wichtig bei solchen FFT-Multiplikationen ist das Wörtchen "asympthotisch", denn es bedeutet das die Performance-Kurve im Verhältnis zu den Zahlengrößen eben NICHT linear sondern sprunghaft ist. D.h. die FFT berechnet immer in weiten Schranken unterschiedlich große Zahlen mit gleicher Geschwindigkeit. Erst wenn bestimmte Zahlkengrößen überschrittten werden steigt der Zeitaufwand der FFT sprunghaft an. Sozusagen entsteht eine Treppenfunktion in der Performance beim Ansteigen der Zahlengrößen. Nun, Ziel der Optimierung wäre es die Formeln so umzustellen das sie bei der Multiplizierung eben diese Treppenfunktion=asymptotisches Verhalten der FFT berücksichtigt. Kurz gesgt: es ist für die meisten FFT's am besten wenn die Zahlengröße in Bits ein Vielfaches von 2 ist. 6.) An vielen Stellen mit sehr wichtigen math. Funktionen habe ich in Assembler optimiert. Dabei wurden auch die neueren SSE2 Features der CPU's berücksichtigt. Beim SSE2 kann man sagen das dies ein mindestens 2 mal höhere Performance erzeugt. Allerdings es gibt noch genügend Source-Stückchen die noch nicht mit solchem SSE2 Code programmiert sind. Besodners die Funktionen für die FFT hätten das noch Potential. Ziel der Optimierung wäre es also diese wichtigen Sources in SSE2 Assembler zu coden. 7.) ein weiteres Beispiel für eine solche Optimierung ist der verwendete Division Algortihmus. Auch dieser basiert auf dem "Divide and Conquer" Verfahren. Der benutzte Algorithums ist der zur Zeit schnellste bekannte, die "Fast Recursive Karatsuba Division" von Burnikel & Ziegler. Auch dieser Algo. zerlegt das Gesamtproblem der Division in viel immer kleiner werdende Divisionen + Multiplikationen. Die kleinest Einheit von Divisions-Algo. ist aber eine normale Assemblercodierte Division nach Donald E. Knuth. Dieser Code ist aber in i486 Code programmiert. Ziel der Optimierung wäre es diesen Algo. auf SSE2 zu portieren. Dadurch düfte die Division im gesammten ca. 2 mal schneller werden. In einigen Performance-Vergleichen zu anderen Pi-Berechnugs-Programmen zeigte es sich das gerade meine Division um den Faktor 2 bis 3 langsammer ist als die der Konkurrenten. Dies liegt hauptsächlich daran das dieses Programme eine komplett andere Division von großen Zahlen benutzten. Die meisten nutzen eine Reziprokale Division die auf einer Newton Iteration basiert. Normalerweise ist dieser Algo. ineffizienter als der von mir benutzte, mit einer einzigsten Ausnahme. Eben der Divsion von sehr sehr großen Zahlen die die besonderen Eigenschaften besitzen wie sie bei der Pi-Formel von Natur aus entstehen. Somit wäre ein zweite Ziel der Oprimierung diese Reziprokale Division zu codieren. 8.) mein Speichermanagement für die IInteger ist darauf ausgelegt möglichst uuniversell flexibel zu sein. Dies äußerst sich auch darin das im Zahlenbereich bis zu ca. 500.000 Dezimalstellen von Pi mein jetziger Code eben schon ca. 2 mal schneller ist als die anderen Programme. D.h. mein Speichermanagement ist enorm effizient für kleinere Zahlen für kryptographische Algortihmen. Will man aber sehr große Zahlen berechnen, wie eben Pi, so ist es sinnvoller eine komplett andere Strategie im Speichermanagement zu verfolgen. Statt die viele kleinen Speicherzugriffe zu optimieren wird es bei großen Zahlen wichtig den Speicher möglichst linear wiederzuverwenden. Ziel der Optimierung wäre es also alle FFT Operationen innerhalb eines einmalig sehr groß allozierten Speicherbereiches inplaced durchzuführen. Dies bedingt aber eine komplette Neuprogrammierung der internen Zahlendarstellungen und Speicherzugriffe. 9.) der von mir benutzte Binary Splitting Algorithmus enthält eine partielle Formel-Optimierung. D.h. er optimiert bis zu einer Tiefe von 4, bestimmmte Multiplikationen weg. Theoretisch könnte man diese Optimierungstiefe aber viel stärker ausbauen. Dazu müssten alle Zwischenresulate der Callback bekannt sein. Nun könnte man das Bin. Splitting so optimieren das es mit der geringsten Anzahl an nötigen Multiplikationen arbeitet. Allein dies dürfte das Vrfahren mindestens 2 bis 3 mal beschleunigen. Allerdings steigt der Speicherverbrauch enorm an. Alles in allem würde ich schätzen das alle obigen Optimierungen meine Pi Berechnungen ca. 3 bis 5 mal schneller machen könnten. Damit wäre diese in der Performance ca. 2 mal schneller als das schnellste Pi Programm das es zur Zeit für PC's gibt. Allerdings, jede der obigen Optimierungen ist wesentlich komplizierter als es die jetzigen Algorithmen eh schon sind. D.h. es ist nicht so einfach wie es sich anhört. Alle bisherigen Algos. sind von mir schon bis zur max. Leistungsgrenze hin optimiert worden. Gruß Hagen Hier mal der Binary Spliting Code von mir:
Delphi-Quellcode:
type
TIIntegerSplitData = packed record P,Q,A,B: IInteger; end; TIIntegerBinarySplittingCallback = procedure(N: Cardinal; var P: TIIntegerSplitData); register; function NBinarySplitting(var P,Q: IInteger; Count: Integer; Callback: TIIntegerBinarySplittingCallback; ImplicitShift: Boolean = True): Cardinal; type TSplitParam = packed record P,Q,A,B: IInteger; Callback: TIIntegerBinarySplittingCallback; CallerEBP: Cardinal; CalcP: Boolean; end; function BinarySplitting(n1,n2: Cardinal; var R: TSplitParam): Cardinal; procedure Split_C(n: Cardinal; var R: TSplitParam); asm PUSH [EDX].TSplitParam.CallerEBP CALL [EDX].TSplitParam.CallBack POP EAX end; function Split_1(n: Cardinal; var R: TSplitParam): Cardinal; begin Split_C(n, R); if R.P <> nil then if R.A <> nil then NMul(R.A, R.P) else R.A := R.P; if R.Q <> nil then Result := NShr(R.Q) else Result := 0; end; function Split_2(n: Cardinal; var R: TSplitParam): Cardinal; var L: TSplitParam; rQs,lQs: Cardinal; begin rQs := 0; lQs := 0; L.Callback := R.Callback; L.CallerEBP := R.CallerEBP; L.CalcP := True; Split_C(n +0, L); Split_C(n +1, R); // L.A := (L.A * R.B * R.Q * L.P) shl rQs; // R.P = R.P * L.P; // R.Q = R.Q * L.Q; // R.B = R.B * L.B; // R.A = R.A * L.B * R.P + L.A; if R.Q <> nil then begin rQs := NShr(R.Q); if L.A <> nil then NMul(L.A, R.Q) else NSet(L.A, R.Q); end else if L.A = nil then NSet(L.A, 1); if L.Q <> nil then begin lQs := NShr(L.Q); if R.Q <> nil then NMul(R.Q, L.Q) else NSwp(R.Q, L.Q); end; if L.B <> nil then if R.A <> nil then NMul(R.A, L.B) else R.A := L.B; if R.B <> nil then begin NMul(L.A, R.B); if L.B <> nil then NMul(R.B, L.B); end else NSwp(R.B, L.B); if L.P <> nil then begin NMul(L.A, L.P); if R.P <> nil then NMul(R.P, L.P) else NSwp(R.P, L.P); end; if R.P <> nil then if R.A <> nil then NMul(R.A, R.P) else R.A := R.P; if rQs > 0 then NShl(L.A, rQs); if R.A = nil then begin NSwp(R.A, L.A); NInc(R.A); end else NAdd(R.A, L.A); Result := rQs + lQs; end; function Split_3(n: Cardinal; var R: TSplitParam): Cardinal; var L,M: TSplitParam; rQs,lQs,mQs: Cardinal; begin lQs := 0; mQs := 0; rQs := 0; L.Callback := R.Callback; L.CallerEBP := R.CallerEBP; M.Callback := R.Callback; M.CallerEBP := R.CallerEBP; Split_C(n +0, L); Split_C(n +1, M); Split_C(n +2, R); if L.Q <> nil then lQs := NShr(L.Q); if M.Q <> nil then mQs := NShr(M.Q); if R.Q <> nil then rQs := NShr(R.Q); // P := [R.P * [M.P * L.P]] // Q := [R.Q * M.Q] * L.Q // B := [R.B * M.B] * L.B // R.A := ([R.B * M.B] * [R.Q * M.Q] * L.A * L.P) shl (rQs + mQs) + // (([M.P * L.P] * R.B * R.Q * M.A) shl rQs) * L.B + // [R.P * M.P * L.P] * M.B * R.A // R.P := P // R.Q := Q // R.B := B if L.P <> nil then if M.P <> nil then NMul(M.P, L.P) else M.P := L.P; if M.P <> nil then if R.P <> nil then NMul(R.P, M.P) else R.P := M.P; if M.A = nil then NSet(M.A, 1); if M.P <> nil then NMul(M.A, M.P); if R.B <> nil then NMul(M.A, R.B); if R.Q <> nil then NMul(M.A, R.Q); if rQs > 0 then NShl(M.A, rQs); if R.A = nil then NSet(R.A, 1); if R.P <> nil then NMul(R.A, R.P); if M.B <> nil then NMul(R.A, M.B); NAdd(R.A, M.A); if L.B <> nil then NMul(R.A, L.B); if M.Q <> nil then if R.Q <> nil then NMul(R.Q, M.Q) else R.Q := M.Q; if M.B <> nil then if R.B <> nil then NMul(R.B, M.B) else R.B := M.B; if L.A = nil then NSet(L.A, 1); if L.P <> nil then NMul(L.A, L.P); if R.B <> nil then NMul(L.A, R.B); if R.Q <> nil then NMul(L.A, R.Q); Inc(rQs, mQs); if rQs > 0 then NShl(L.A, rQs); NAdd(R.A, L.A); if L.Q <> nil then if R.Q <> nil then NMul(R.Q, L.Q) else R.Q := L.Q; if L.B <> nil then if R.B <> nil then NMul(R.B, L.B) else R.B := L.B; Result := lQs + rQs; end; function Split_4(n: Cardinal; var R: TSplitParam): Cardinal; var L,M,K: TSplitParam; rQs,mQs,kQs,lQs: Cardinal; begin lQs := 0; mQs := 0; kQs := 0; rQs := 0; L.Callback := R.Callback; L.CallerEBP := R.CallerEBP; M.Callback := R.Callback; M.CallerEBP := R.CallerEBP; K.Callback := R.Callback; K.CallerEBP := R.CallerEBP; Split_C(n +0, L); Split_C(n +1, M); Split_C(n +2, K); Split_C(n +3, R); if L.Q <> nil then lQs := NShr(L.Q); if M.Q <> nil then mQs := NShr(M.Q); if K.Q <> nil then kQs := NShr(K.Q); if R.Q <> nil then rQs := NShr(R.Q); if L.P <> nil then if M.P <> nil then NMul(M.P, L.P) else M.P := L.P; if M.P <> nil then if K.P <> nil then NMul(K.P, M.P) else K.P := M.P; if K.P <> nil then if R.P <> nil then NMul(R.P, K.P) else R.P := K.P; if M.A = nil then NSet(M.A, 1); if M.P <> nil then NMul(M.A, M.P); if L.B <> nil then NMul(M.A, L.B); if R.Q <> nil then if K.Q <> nil then NMul(K.Q, R.Q) else K.Q := R.Q; if K.Q <> nil then NMul(M.A, K.Q); if M.Q <> nil then NMul(K.Q, M.Q); if L.A = nil then NSet(L.A, 1); if L.P <> nil then NMul(L.A, L.P); if K.Q <> nil then NMul(L.A, K.Q); if M.B <> nil then NMul(L.A, M.B); if mQs > 0 then NShl(L.A, mQs); NAdd(L.A, M.A); if R.B <> nil then if K.B <> nil then NMul(K.B, R.B) else K.B := R.B; if K.B <> nil then NMul(L.A, K.B); Inc(kQs, rQs); if kQs > 0 then NShl(L.A, kQs); if K.A = nil then NSet(K.A, 1); if K.P <> nil then NMul(K.A, K.P); if R.Q <> nil then NMul(K.A, R.Q); if R.B <> nil then NMul(K.A, R.B); if rQs > 0 then NShl(K.A, rQs); if R.A = nil then NSet(R.A, 1); if R.P <> nil then NMul(R.A, R.P); if K.B <> nil then NMul(R.A, K.B); NAdd(R.A, K.A); if M.B <> nil then if L.B <> nil then NMul(L.B, M.B) else L.B := M.B; if L.B <> nil then NMul(R.A, L.B); NAdd(R.A, L.A); NSwp(R.Q, L.Q); if K.Q <> nil then if R.Q <> nil then NMul(R.Q, K.Q) else NSwp(R.Q, K.Q); NSwp(R.B, L.B); if K.B <> nil then if R.B <> nil then NMul(R.B, K.B) else NSwp(R.B, K.B); Result := lQs + kQs + mQs; end; function Split_D(n1, n2: Cardinal; var R: TSplitParam): Cardinal; var L: TSplitParam; nM,lQs,rQs: Cardinal; begin nM := (n1 + n2) shr 1; L.Callback := R.Callback; L.CallerEBP := R.CallerEBP; L.CalcP := True; lQs := BinarySplitting(n1, nM, L); rQs := BinarySplitting(nM, n2, R); // R.A := (R.A * L.B * L.P) + (L.A * R.B * R.Q) shl rQs // R.P := R.P * L.P // R.Q := R.Q * L.Q // R.B := R.B * L.B if R.B <> nil then begin if R.Q <> nil then begin if L.A <> nil then begin NMul(L.A, R.B); NMul(L.A, R.Q); if rQs > 0 then NShl(L.A, rQs); end else begin NMul(L.A, R.B, R.Q); if rQs > 0 then NShl(L.A, rQs); end; end else L.A := R.B; end else if R.Q <> nil then if L.A <> nil then begin NMul(L.A, R.Q); if rQs > 0 then NShl(L.A, rQs); end else if rQs > 0 then NShl(L.A, R.Q, rQs) else L.A := R.Q; if L.B <> nil then begin if R.A <> nil then begin NMul(R.A, L.B); if L.P <> nil then NMul(R.A, L.P); end else if L.P <> nil then NMul(R.A, L.B, L.P); end else if L.P <> nil then if R.A <> nil then NMul(R.A, L.P) else NSet(R.A, L.P); if R.A = nil then begin NSwp(R.A, L.A); NInc(R.A); end else if L.A <> nil then NAdd(R.A, L.A) else NInc(R.A); if R.CalcP then if L.P <> nil then if R.P <> nil then NMul(R.P, L.P) else NSwp(R.P, L.P); if L.Q <> nil then if R.Q <> nil then NMul(R.Q, L.Q) else NSwp(R.Q, L.B); if L.B <> nil then if R.B <> nil then NMul(R.B, L.B) else NSwp(R.B, L.B); Result := lQs + rQs; end; resourcestring sNBinarySplitting = 'NBinarySplitting(), internal error index = 0'; begin case n2 - n1 of 0: begin NRaise(@sNBinarySplitting); Result := 0; end; 1: Result := Split_1(n1, R); 2: Result := Split_2(n1, R); 3: Result := Split_3(n1, R); 4: Result := Split_4(n1, R); else begin Result := Split_D(n1, n2, R); end; end; end; // apply a custom binary splitting computation for linear convergent series // // p[0]...p[n] a[n] // S = P / Q = sum(n=0..Count -1) ----------- ---- // q[0]...q[n] b[n] // // TI97-7.ps, Fast multiprecision evaluation of series of rational numbers // Bruno Haible & Thomas Papanikolaou // for each coefficient p[n], q[n], a[n], b[n] are callback(N, P, Q, A, B) called. // The custom callback procedure can access as nested procedure to the owner stack. // If the IIntegers P,Q,A,B of the callback are unchanged = not assigned = NIL then // there assumed to a value of +1. That reduce memory, interfaces and speedup. // Means we can implicate that the callback is called by Callback(n, 1, 1, 1, 1); resourcestring sNBinarySplitting = 'NBinarySplitting(), Count must be >= 0 and Callback <> nil'; var D: TSplitParam; begin if (Count < 0) or not Assigned(Callback) then NRaise(@sNBinarySplitting); if Count = 0 then begin NSet(P, 0); NSet(Q, 1); Result := 0; end else begin asm MOV EAX,[EBP] MOV D.CallerEBP,EAX end; D.Callback := Callback; D.CalcP := False; Result := BinarySplitting(0, Count, D); if D.B <> nil then if D.Q <> nil then NMul(D.Q, D.B) else NSwp(D.Q, D.B); if ImplicitShift then begin NShl(D.Q, Result); Result := 0; end; NSwp(P, D.A); NSwp(Q, D.Q); end; end; |
Zitat |
Dax
(Gast)
n/a Beiträge |
#52
@negaH:
Ich hab den Binary-Splitting mal "entmüllt" und auf die NPi-Berechnungen angewandt. Der Fast-Chudnovsky wurde bei 500.000 Nachkommastellen tatsächlich 16 ms schneller. Du hast doch auch gepostet, es gäbe "Höherdimensionale" Varianten des Chudnovsky-Algos. Was haben wir dabei unter "Höherdimensional" zu verstehen, und vor allem, wie funktioniert er? BtW: Komm, gib nur die Formeln an, ich will auch mal denken! Und: wie berechnet man die Euler-Zahl e? |
Zitat |
Registriert seit: 25. Jun 2003 Ort: Thüringen 2.950 Beiträge |
#53
Zitat:
Ich hab den Binary-Splitting mal "entmüllt" und auf die NPi-Berechnungen angewandt. Der Fast-Chudnovsky wurde bei 500.000 Nachkommastellen tatsächlich 16 ms schneller.
Aber du könntest mir mal deine Umsetzung mailen.
Zitat:
Du hast doch auch gepostet, es gäbe "Höherdimensionale" Varianten des Chudnovsky-Algos. Was haben wir dabei unter "Höherdimensional" zu verstehen, und vor allem, wie funktioniert er?
1.) man benötigt Rationale Zahlen oder eben Fließkommaarithmetik, dies bringt aber eine gewisse "Unsicherheit" in der Genauigkeit mit sich. D.h. die Dimension in der der Programmiere/Mathematiker seinen Algo. überdenken muß wird höher. 2.) die Formel ansich arbeitet in höherer Dimension, aber dazu solltest du die einschlägigen WEB Seiten/PostScripts studieren. Ich bin einer der Mathematik am liebsten macht wenn ein Problem auch nur mit Halbwissen zu lösen ist. D.h. auch ich verstehe nicht jede Formel zu 100% in all ihren Abgründen, trotzdem kann ich sie programmieren. Nun diese 31 Stellen Chundnovsky Formel ist so ein Monster.
Zitat:
Komm, gib nur die Formeln an, ich will auch mal denken!
Zitat:
Und: wie berechnet man die Euler-Zahl e?
Delphi-Quellcode:
Umgeschrieben bedeutet das für dich
procedure NExp(var A: IInteger; U,V: Integer);
// A = A * e^(U / V) A = A * e^(1/1) = A * e^1 = A * e. Du setzt A z.B. auf A = 10^500000 und rufst danach NExp(A) auf, schon hast du A = e * 10^500000, also die 500000 Dezimalstellen von e. Gruß Hagen |
Zitat |
Dax
(Gast)
n/a Beiträge |
#54
Hi negaH!
Das einzige an "entmüllung" ist, alle if-Dinger mir x.B als Bedingung zu löschen. Ist also nicht wirklich kompliziert |
Zitat |
Registriert seit: 12. Aug 2004 49 Beiträge |
#55
hi negaH
also dein IInteger fasziniert mich ! hättest du nicht lust eine ordentliche lib zum machen so ähnlich wie gmp aber halt für delphi mit ner kleinen beschreibung aller enthaltenen funktionen ? weil leider gib es keine vernünftige BigInt lib für delphi und deine NInts.pas/dcu ist das beste was ich derzeit finden kann hab zwar auch eine gmp-dll aus der ich die gmp-funktionen importe aber das ist keine saubere lösung so ein package für delphi wäre echt ne spitzen sache ! mfg Dano |
Zitat |
Registriert seit: 25. Jun 2003 Ort: Thüringen 2.950 Beiträge |
#56
Danke und ähm
Zitat:
hättest du nicht lust eine ordentliche lib zum machen so ähnlich wie gmp aber halt für delphi mit ner kleinen beschreibung aller enthaltenen funktionen ?
Nee, was du möchtest ist eine OpenSource Bibliothek weil es keine freien Sourcen auf diesem Sektor für Delphi gibt. Und tatsächlich meine IInteger sind keine Freeware, da haste Recht. Ich glaube du unterschätzt den Aufwand erheblicheine solche Lib zu coden (ist ja nicht nur die Programmierung). Ich habe ca. 3 Jahre dran gebastelt, ca. 75% ist in Assembler selbst der SSE2 Befehlssatz wird unterstützt. Aber viel wichtiger sind die Algorithmen, und da kann ich sehr stolz behaupten das selbst die GMP Experten Teams nicht so effiziente Algos. enthalten wie in meiner Lib. Also, bitte warum sollte ich jetzt nun das Bedürfniss haben diese 3 Jahre Spaß mit der Hölle, nochmal zu wiederholen ? Gruß Hagen |
Zitat |
Registriert seit: 12. Dez 2002 Ort: Karlsruhe 1.989 Beiträge |
#57
Zitat von negaH:
Also, bitte warum sollte ich jetzt nun das Bedürfniss haben diese 3 Jahre Spaß mit der Hölle, nochmal zu wiederholen?
Michael N.
http://nailor.devzero.de/code/sharpmath/testing/ --- Tests, Feedback, Anregungen, ... aller Art sehr willkommen! ::: don't try so hard - it'll happen for a reason ::: |
Zitat |
Registriert seit: 25. Jun 2003 Ort: Thüringen 2.950 Beiträge |
#58
sorry, wenn dich meine ausführlichen Antworten stören, dann las ichs einfach, tschüß.
Gruß hagen |
Zitat |
Registriert seit: 26. Nov 2003 Ort: Lünen 1.932 Beiträge Delphi 7 Enterprise |
#59
ich glaube nailor hat das eher scherzhaft bzw. "frotzelig" gemeint...
Komm bloß nicht auf die Idee, nicht mehr so grandios zu antworten! Ich verstehe zwar nicht wirklich immer alles, wenn es so ins Detail geht, aber ich lese sowas immer mit sehr großem Interesse! (Gerade was mathematische Klamotten angeht). Also: Keep cool, and keep on!
Fabian K.
INSERT INTO HandVonFreundin SELECT * FROM Himmel |
Zitat |
Registriert seit: 3. Jul 2004 Ort: Mülheim an der Ruhr 198 Beiträge Delphi 5 Enterprise |
#60
@Hagen ich kann auch nur sagen immer weiter, deine mehr als ausführlichen antworten machen es erst richtig interessant sich hier ein bißchen durchzulesen, vor allem weil mich der mathematische bereich auch sehr interessiert aber man den mit 11. klasse schulbildung noch nich wirklich blickt
also immer weiter so, hör bloß nich auf
if ThisPost is senseless then
ThisPost.WasPostedBy := SomeoneElse(); |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |