Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Beliebige Anzahl an Nachkommastellen??


Toby-1985 - So 01.01.06 14:09
Titel: Beliebige Anzahl an Nachkommastellen??
Hallo zusammen und ein frohes neues Jahr 2006 an alle Delphi-Freunde und Computernarren vorne weg ;-).

Wahrscheinlich gibt es zu meiner Frage schon eine Menge Threads, aber dennoch komme ich nicht drum herum einen neuen zu eröffnen, da mir leider Gottes diese auch nicht bei der Beantwortung meiner Frage helfen konnten. Also seid bitte nachsichtig mit mir und verzeiht mir den neuen Thread.

Meine Frage ist eigentlich ganz einfach, aber für mich schwer eine Antwort drauf zu finden. Ich hoffe, ihr könnt mir helfen.


Wie kann ich eine beliebige Anzahl an Nachkommastellen einstellen? Ich habe bisher nur den Datentyp "Extended" ausprobiert, komme aber nur auf 17 Nachkommastellen. Das ist mir eigentlich noch zu wenig.

Gibt es irgendeinen schon vorinstallierten Datentyp, den ich verwenden kann, der mir eine "beliebige Anzahl" an Nachkommastellen liefert?

Ich wäre für eine Antwort sehr dankbar.


Horst_H - So 01.01.06 14:41

Hallo,

nein.

Gruss Horst
P.S.:
Suche mal nach arbitrary precision
http://www.google.de/search?hl=de&q=arbitrary+precision+float+delphi&btnG=Suche&meta=


BenBE - So 01.01.06 14:47

Steht in der ganzen Unmenge anderer Threads zu diesem Thema bereits klar und deutlich drin: Dafür muss man sich selber etwas schreiben.

Solche Dinge wie BigNum, BigInt, ... brauch ich hoffentlich nicht extra erwähnen ...


delfiphan - So 01.01.06 19:32

Und wieder kommt die Frage nach dem Zweck: Was möchtest du damit berechnen? Es gibt oft eine bessere Lösung bzw. spezialisierte Algorithmen für spezielle Anwendungen. "Arbritrary Precision" ist ein grosser Luxus: Kostet dich sehr viel Ressourcen.


Toby-1985 - So 01.01.06 20:19

Ja ja, der Zweck. Ich hab vor die "Euler'sche Zahl" e auf gut 1000 Nachkommastellen exakt zu berechnen. Mittlerweile sind mir auch die Integerwerte dafür zu klein, denn bei immer größer werdendem Exponenten n, gemäß der Formel : e = (1+(1/n))^n (mit n gegen unendlich), nimmt ja bekanntlich auch die Präzision zu. Ich hab jetzt gerade mal einen maximalen Exponenten von 2,1 Milliarden erreicht und alles, was darüber hinaus geht, scheint nicht mehr zu funktionieren, da ich anscheinend die Grenzen des Integerdatentyps verlasse.

Leider ist mir auch kein anderes Verfahren zur Berechnung bekannt, sodass ich auf die Grenzwertberechnung zurückgreifen muss.

Was die "Arbritrary Precision" angeht.... davon hab ich keinen blassen Schimmer. Ich suche doch nur nach einer einfachen Möglichkeit die Nachkommastellenzahl einfach auswählen zu können, ohne dass ich mit Integers u.a. rumhantieren muss. Aber das scheint es ja "leider" nicht zu geben.

Ich würde mich aber über weitere Anmerkungen, sowie Anregungen freuen, egal, ob sie mir weiterhelfen können oder nicht ;-).


AXMD - So 01.01.06 20:37

user profile iconToby-1985 hat folgendes geschrieben:
Leider ist mir auch kein anderes Verfahren zur Berechnung bekannt


Es gibt mit Sicherheit noch ein anderes. Denn das von dir angegebene ist das einfachste ;). Wie wäre es beispielsweise mit Taylor-Reihen?

AXMD


Toby-1985 - So 01.01.06 20:41

user profile iconAXMD hat folgendes geschrieben:

Wie wäre es beispielsweise mit Taylor-Reihen?

AXMD


Tjoar, wenn ich da einen Plan von hätte, ..., gerne ;-) . Hab ich aber nicht, aber ich muss das ja nicht berechnen.... das macht ja mein Compi zum Glück. Der ist da ja ein "bisschen" schneller als ich.


AXMD - So 01.01.06 20:50

Also die Taylor-Reihe von e^x findest du wirklich überall. Und Formeln ausprogrammiern sollte doch nun wirklich nicht das Problem sein, oder?

AXMD


Toby-1985 - So 01.01.06 20:56

So, hab gerade was dazu gefunden. Damit konnte ich den Exponenten von 2,1 Milliarden auf 200 runtersetzen, nur dass ich jetzt nicht mehr potenziere, sondern einfach aufaddiere durch Schachtelungen. Das hat schon mal Zeit gespart und das Problem mit den Integergrenzen hat sich erledigt. Danke dir für den Tipp mit den Taylorreihen.

Jetzt wieder zu meinem ursprünglichen Problem. Ich möchte ca. 1000 Nachkommastellen berechnen (lassen). Wenn möglich auch noch mehr, selbst wenn es Speicher kosten sollte.

Wäre schön, wenn du für dieses Problem auch noch einen "Geistesblitz" hättest ;-).


Allesquarks - So 01.01.06 20:56

Tja wenn man von so was keinen Plan hat sollte man das sein lassen.

Immer zu denken der Compi rechnet zur Not ein bisschen länger und aus falsch wird richtig ist erschreckend.

Wenn du das ernst meinst dann schau im Inet unter Taylorreihe nach und entwickel die e-Funktion in eine und setze eins an geeigneter Stelle ein dann bekommst du einen viel besseren Algorithmus aufgezeigt.

Nebenbei: Ist dir schon einmal in den Sinn gekommen, dass du bei solchen Rechnungen ja wissen musst wann du aufhören musst zu rechnen Stichwort Fehlerabschätzung. die will ich für deinen Vorschlag gar nicht erst machen. Bei diser Taylorreihe ist dieser nebenbei immer kleiner als das letzte Summenglied. Jetzt musst du dir also überlegen mit welcher genauigkeit du die einzelnen Summenglieder berechnen musst.


BenBE - So 01.01.06 21:07

Naja, wenn's nur das ist:

Such im Forum mal nach BigNum (Unit von mir). Dort geht das mit <10 IIRC.
Zu beachten ist aber, dass Du bei meiner Unit Zähler und Nenner getrennt berechnen musst (was aber kein wirkliches Problem darstellen sollte.


Quelltext
1:
2:
3:
(n+1)^n
------- => e
  n^n


Das mit den Funktionscalls für die BigNum-Unit bauen und dann in's dezimale konvertieren lassen *g*


delfiphan - Mo 02.01.06 15:00

Na dann mal viel Spass. Zum kontrollieren kannst du ja hier nachschauen: http://antwrp.gsfc.nasa.gov/htmltest/gifcity/e.1mil
(n+1)^n/n^n scheint nur sehr langsam zu konvergieren. Auch wenn man n = 100 einsetzt ist das Resultat nicht mal auf 3 Stellen genau, obwohl man mit Zahlen rechnet, die fast 200 Stellen lang sind.

Ich bin zwar kein Experte in diesem Gebiet, aber wenn du die simple Reihe 1+1/1!+1/2!+1/3!+1/4!+... berechnest bist du vielleicht schneller am Ziel. Man braucht ca. 120 solche Terme um e auf 200 Stellen genau zu bekommen.

Du summierst also:
2+
1/2+
1/2/3+
1/2/3/4+
1/2/3/4/5+
...
Wie du siehst kannst du für einen Schritt immer den letzten recyclen. Eine schriftliche Division im Dezimalsystem für eine feste Anzahl Kommastellen sollte doch eigentlich noch zu programmieren sein. Die Addition ist dann noch viel einfacher zu implementieren.


Aristoteles - Fr 06.01.06 17:01

user profile iconToby-1985 hat folgendes geschrieben:
Ich hab jetzt gerade mal einen maximalen Exponenten von 2,1 Milliarden erreicht und alles, was darüber hinaus geht, scheint nicht mehr zu funktionieren, da ich anscheinend die Grenzen des Integerdatentyps verlasse.


Wahrscheinlich verwendest du den Typ "Integer". Damit definierte Variablen können alle ganzen Zahlen bis 2^31=2,1 Mrd. erfassen. Dann ist schluss.

Nun gibt es in Delphi noch den Datentypen "int64". Hiermit definierte Variablen können Werte bis 2^63 speichern (Doppelt so große Stellenanzahl wie integer). Eventuell reicht es also aus, wenn du deinen Datentyp integer durch int64 ersetzt.

Wenn auch int64 nicht ausreicht, musst du zwangsläufig auf Routinen wie die von BenBE verwenden oder - bei ausreichender Motivation - eigene schreiben, die genau an die Ansprüche angepasst sind.


Fiete - Mi 03.10.07 14:41
Titel: Re: Beliebige Anzahl an Nachkommastellen??
Über eine Reihenentwicklung gehts am schnellsten.

mein Vorschlag:

// e=1/0!+1/1!+1/2!+1/3!+1/4!+1/5!+...
// oder
// e=1/0!+1/1!+1/1!/2+1/2!/3+1/3!/4+1/4!/5+...

die Hauptroutine


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:
   ZiffernAnzahl:=SpinEditN.Value;Ausgabe.Clear;

   Digits:=trunc(20-ln(ZiffernAnzahl)/ln(10)); // 10-er Exponent
   Basis:=1;
   for K:=1 to Digits do Basis:=Basis*10;      // 10-er Potenz
   ArraySize:=trunc(ZiffernAnzahl/Digits+2);N:=1.0;AltN:=N;
   SetLength(FakSumme,ArraySize+1);
   SetLength(Summand,ArraySize+1);
   FakSumme[ArraySize]:=2;Summand[ArraySize]:=1;
   for K:=1 to ArraySize-1 do begin FakSumme[K]:=0;Summand[K]:=0 end;
   repeat
    N:=N+1.0;Rest:=0;
    for K:=ArraySize downto 1 do // neuen Fakultätssummand berechnen
     begin
      Wert:=Rest*Basis+Summand[K];
      Summand[K]:=int(Wert/N);Rest:=Wert-N*Summand[K];
     end;
    Uebertrag:=0;
    for K:=1 to ArraySize do // Summe aktualisieren
     begin
      Wert:=FakSumme[K]+Summand[K]+Uebertrag;
      Uebertrag:=int(Wert/Basis);
      FakSumme[K]:=Wert-Uebertrag*Basis
     end;
   until (Summand[1]<=1.0and (N>2); // mindestens zwei Durchläufe

Der Rest ist im Anhang

Gruß, Fiete

Moderiert von user profile iconGausi: Delphi-Tags hinzugefügt