Phi und der goldene Schnitt



  • Also, es geht um die Näherung einer Irrationalen Zahl, dementsprechend brauche ich möglichst viele Nachkommastellen, wenn es geht beliebig viele.

    Edit: einer Rationalen Zahl... 😉



  • long double mit 80 Bit

    type:

    float 3,4E-38 3,4E+38 32
    double 1,7E-308 1,7E+308 64
    long double 3,4E-4932 1,1E+4932 80



  • Danke, aber mit long double hab ich es schon ein Mal versucht (siehe Code), oder versteh ich dich falsch?



  • ups.. das hab ich übersehen... ist denn long double immer noch nich genug??

    hat doch schon ewig viel stellen.....

    könntest ne klasse schreiben welche rationale zahlen emuliert, char /bytes array anlegen eine byte pro stelle... aber performance technisch ist das dann schlecht.. aber glaub größere zahlen gibts net.. muss die zahl negativ sowie positiv sein



  • @Boris: Erstens ist afaik nicht garantiert, daß long double wirklich größer ist als double. Und zweitens hat der Wertebereich nur indirekt etwas mit der Anzahl der Nachkommastellen zu tun (die dürften so bei 8..10 liegen, müsste ich mal nachgucken).

    @ne0r: Wenn dir die Genauigkeit der eingebauten Datentypen nicht reicht, mußt du dir eine andere Bibliothek suchen (evt. wäre GMP geeignet)

    PS: Und der goldene Schnitt IST irrational 😉



  • CStoll schrieb:

    @Boris: Erstens ist afaik nicht garantiert, daß long double wirklich größer ist als double. Und zweitens hat der Wertebereich nur indirekt etwas mit der Anzahl der Nachkommastellen zu tun (die dürften so bei 8..10 liegen, müsste ich mal nachgucken).

    Warum nur indirekt? Sind doch Fließkommazahlen, müsste man doch direkt aus dem Wertebereich herleiten können, wieviel Nachkommastellen möglich sind 😕
    Oder kann das Komma nicht überall hin-fließen?



  • Hast du dir die Darstellung von Gleitkomma-Zahlen mal angesehen? Die werden intern gespeichert als m*2e, dabei werden die Bits aufgeteilt auf Vorzeichen, Mantisse m (die bestimmt die Anzahl der Nachkommastellen) und Exponent e (der bestimmt den Wertebereich). Dadurch kannst du keine absolute Anzahl an "Nachkommastellen" angeben, sondern nur eine Anzahl an signifikanten Stellen (deren Position bezüglich des Kommas variieren kann):

    15 hat zwei signifikante Stellen, aber keine Nachkommastellen.
    1.5 hat ebenfalls zwei signifikante Stellen und 1 Nachkommastelle.
    ...



  • PS: Und der goldene Schnitt IST irrational 😉

    Arghs, ich meinte reell, so!^^

    Jo, double/long double geben nach meiner bisherigen Erfahrung und einem Tutorial beide 16 Nachkommastellen. Oder vielleicht 15, die dafür auch stimmen 😉

    Hmm. GMP ist zwar eine nette Idee, aber ich denke, ich werd mir lieber eine eigene Klasse schreiben ^^ Mal schaun, ob das klappt.



  • für was ein programm? der goldene schnitt lässt sich ganz einfach analytisch lösen:
    1 : x = (1+x) : 1
    1 = 1*x + x^2
    0.5 = 0.5*x + 0.5*x^2
    0 = 0.5*x^2 + 0.5*x - 0.5
    x[1,2] = -0.5 +- sqrt(0.25 + 4*0.5*0.5)
    (unter ausschluss der negativen Lösung)
    x = -1/2 + sqrt(5/4)

    ==> Goldener Schnitt: 1 : (sqrt(5/4) - 1/2)



  • [quote}für was ein programm? der goldene schnitt lässt sich ganz einfach analytisch lösen[/quote]

    Stimmt. 😉

    Naja, was solls.

    😉



  • pagr schrieb:

    für was ein programm? der goldene schnitt lässt sich ganz einfach analytisch lösen:
    ==> Goldener Schnitt: 1 : (sqrt(5/4) - 1/2)

    und nu? wie radiziert man mit sehr vielen stellen?
    da würd ich ja schon lieber die fixpunktiteration double phi=2;for(;;){cout<<(phi=1/phi+1)<<'\n';} nehmen. aber am besten deucht mich, einfach zwei möglichst lange fibonacci-zahlen (als ganzzahl) zu basteln und die zu dividieren (gerne auch als ganzzahl nach multiplikation des zählers mit einer zehnerpotenz).



  • Hmm... das mit den Fibonacci-Zahlen klingt sehr brauchbar.

    Denn man könnte ja eine Funktion definieren, die so zu sagen wie mit Stift und Papier dividiert, sprich nicht das Ergebnis in eine Variable ausgibt, sondern Stelle für Stelle auf den Bildschirm.

    Hmmm. Mache mich an die Arbeit 😉



  • Also so weit wär ich:

    #include <iostream>
    #include <iomanip>
    #include <cmath>
    using namespace std;
    
    void divide(unsigned long a, unsigned long b, int count) {
    	cout<<a/b;
    	a = (a%b)*10;
    	cout<<".";
    	while(count>0) {
    		cout<<a/b;
    		a = (a%b)*10;
    		count--;
    	}
    }
    
    int main() {
    	cout<<setprecision(16);
    	cout<<"(1+sqrt(5))/2 = "<<(1+sqrt(5))/2<<"..."<<endl<<endl;
    
    	unsigned long a,b;
    	int count;
    	a = 0;
    	b = 1;
    	count = 21;
    	while(count > 0) {
    		a = a+b;
    		b = a+b;
    		count--;
    	}
    	a = a+b;
    	cout<<"Fibonacci(44) / Fibonacci(43) ="<<endl;
    	cout<<a<<" / "<<b<<" = "<<endl<<endl;
    	divide(a,b, 1000);
    	cout<<"..."<<endl;
    
    	fflush(stdin);
    	getchar();
    	return 0;
    }
    

    Errechnet die Fibonacci 44 und 43 (Mehr geht nich, auch nich mit unsigned short...) und teilt diese, nur dass nicht in Variablen gespeichert wird, sondern direkt an Prompt ausgegeben (Zeichen für Zeichen). Sprich: Keine Speicherprobleme. Dafür isses nich sehr genau... Aber das muss reichen. ^^



  • ne0r schrieb:

    Errechnet die Fibonacci 44 und 43 (Mehr geht nich, auch nich mit unsigned short...)

    Wenn dir der Speicherbereich nicht reicht, solltest du einen größeren Datentyp verwenden (unsigned short ist normalerweise deutlich kleiner als unsigned long ;)), z.B. 'long long' oder __int64

    (oder du denkst nochmal über GMP nach)



  • ne0r schrieb:

    void divide(unsigned long a, unsigned long b, int count) {
    cout<<a/b;
    a = (a%b)*10;
    cout<<".";
    while(count>0) {
    cout<<a/b;
    a = (a%b)*10;
    count--;
    }
    }

    jup. sieht fein aus.
    und nur bau die ne funktion a=a%b, die ohne division auskommt. zweck soll sein, daß du dir ne langzahlklasse bauen kannst, die mit + und - und < auskommt. die ist nämlich ruck zuck gebaut, wärend dividieren mit langzahlen schon eher zu den unspaßigen jobs gehört.
    ich denke da an sowas wie

    //erstmal b solange vordoppel, wie es geht und nicht größer a wird
    //dann runterhalbieren und immer wenn möglich von a abziehen
    

    die andere funktion
    a=a*10
    wäre vielleicht möglich als
    //ungetestet
    x=a+a; a=x+x; a=a+a; a=a+x;



  • Ich meinte unsigned long...

    Ich habe eh vor, mir eine Langzahlklasse zu bauen, nur solange ich noch so wenig Erfahrung habe, erscheint mir dieser Job ziemlich frustrierend werden zu können, also schau ich mir noch mal en paar Tutorials an und schau dann weiter 😉

    Danke für die Antworten!

    @Volkard: Deine Funktion gibt, glaub ich, 12a raus statt 10a...

    Besser wäre glaube ich:

    (Beispiel mit Standart Datentypen)

    double multi(double a, double b) {
    double e = 0;
    while(b>0) {
    e += a;
    b--;
    }
    return e;
    }
    

    (Ok, was mach ich, wenn b nicht ganzzahlig ist? XD, muss ich noch überlegen ;D);


Anmelden zum Antworten