Funktionswert einer Reihenentwicklung

ocsme

Top Contributor
Guten Tag,

ich hatte gerade mal etwas Zeit und habe meine Formelsammlung versucht weiter aufzubessern. Hab schon einige Funktionen selbst Programmiert.
Nun sitze ich vor einem Problem und komme nicht ganz zurecht 🙁
Die Funktion ist: f(x)=(1/Math.sqrt(1+x)) Für alle |x| < 1
Die Potenzreihe sieht wie folgt aus:
1-(1/2)*x+(3/8)*x*x-(15/48)x*x*x+...
Wie man sieht stehen im Nenner alle ungeraden (n*2-1) Produkte und im Zähler die geraden also (n*2) Produkte.

Das ganze hab ich so Programmiert:
Java:
public static double f(double x) {
        double basis=x;
        int k=0;
        double product=1;
        int n=1;
        double an=1;
        double sn=1;
        while(Math.abs(an)>EPSILON*Math.abs(sn)) {
            k=n;
            while(k>0) {
                product*=basis;
                k--;
            }
            an*=-(2*n-1)*product/(2*n);
            sn+=an;
            n++;
        }
        return sn;
    }

Problem ist:
bei der Eingabe von:
Java:
System.out.println(f(.9));
        System.out.println(1/Math.sqrt(1+.9));
bekomme ich eine abweichung von 0.01...
0.7147474611281968
0.7254762501100117
Und das ganze wird nicht besser bei anderen Zahlen 🙁

Ich finde den Fehler leider nicht.

Vielleicht hat ja jemand eine Idee 🙂

LG
 
huppsi das ist ganz oben in der Klasse definiert und gleich vergessen worden 😀
Java:
public final static double EPSILON = 1E-16;

Ich weiß auch dass, das Potenzieren in meiner Funktion nicht so schön ist denn wenn man das Nachfolgeglied der Reihe berechnen würde wäre es eleganter.
Doch leider habe ich mich dabei noch mehr verrechnet 🙁 deswegen hab ich es so gemacht 🙂
 
Hatte es falsch da Zähler und Nenner falsch waren oben.
Jetzt stimmt es zwar annähernd doch leider bekomme ich bei Epsilon 1e-9 und größer nan raus 🙁
Java:
public static double f(double x) {
        int n=1,k,l,m;
        boolean plus=false;
        double nachfolger=0, abstand=1, vorgaenger=x, result=1;
        double tmp, productzaehler=1, productnenner=1,potenz=1;
       
        while(abstand>EPSILON) {
            abstand=vorgaenger-nachfolger;
            if(abstand<0)
                abstand=-abstand;
            vorgaenger=nachfolger;
           
            k=n;
            l=n;
            m=n;
            while(k>0) {
                potenz*=x;
                k--;
            }
            while(l>0) {
                productzaehler*=2*l-1;
                l--;
            }
            while(m>0) {
                productnenner*=2*m;
                m--;
            }
           
            tmp=productzaehler*potenz/productnenner;
            if(!plus)
                tmp=-tmp;

            result+=tmp;
            nachfolger=result;
            System.out.println(abstand);
            plus=!plus;
            n++;
            productzaehler=1;
            productnenner=1;
            potenz=1;
           
        }
        return result;
    }
 
Ohne jetzt auf etwaige Fehler Deines Codes einzugehen (das ist mir zu kompliziert 🙂) ist das grundsätzliche Problem, dass die Zahlen relativ zügig den Wertebereich verlassen, wenn Du Zähler und Nenner separat ausrechnest.

Ich würde mir einfach mal anschauen, ob ich die Folgeglieder nicht rekursiv angeben kann... Wie entsteht denn das n-te Folgeglied aus dem (n-1)-ten?
 
Interessante Idee 🙂
Denke das werde ich mir mal überlegen 🙂
Noch eine andere Frage wo kann ich den vernünftig etwas über UML nachlesen? Vor allem zu den Klassendiagrammen was das Thema Vererbung (Interface, ABC und extends (vererbten) Klassen) angeht?
Ich weiß zwar wie eine Klasse aussehen muss im UML etc. doch die Begriffe: Assoziationen, Aggregationen, Kompositionen oder Spezialisierungen z. B. wollte ich mal nachschlagen. Im Internet habe ich nichts wirklich auf Anhieb brauchbares gefunden 🙁

LG
 
In der Spezifikation, die ist aber nichts für schwache Nerven 🙂
https://www.omg.org/spec/UML/About-UML/#docs-normative-supporting

Ansonsten: Assoziation ist eine einfache Beziehung. Aggregation und Kompositionen beschreiben Ganzes-Teile-Beziehungen, wobei Komposition die stärkere ist, die ausdrückt, dass ein Teil zu einem Zeitpunkt immer nur zu einem Ganzen zugehörig sein kann und das dieses Teil ohne das Ganze nicht sinnvoll existieren kann.

Typisches Beispiel für eine Komposition wäre die Beziehung zwischen Rechnung und Rechnungsposition. Eine Rechnungsposition (hier ist das Objekt gemeint) ist klar Teil einer Rechnung, kann nicht zugleich Teil einer anderen Rechnung sein und auch nicht ohne eine Rechnung (sinnvoll) existieren.

Wenn Du dagegen in einem Grafikprogramm eine Gruppe aus grafischen Elementen bildest, dann ist es zwar auch eine Ganzes-Teile-Beziehung, aber nur eine Aggregation: die Elemente können auch gut ohne ihre Gruppe existieren.

Eine Assoziation ist dagegen eine einfach Beziehung. Für den Kunden existieren Rechnungen.

Der Rest (Interfaces, Spezialisierung) sollte relativ einfach zu verstehen sein.
 
Inhaltlich steht da nicht mehr drin als in der FAQ (im Gegenteil, in der FAQ wird noch auf die Zahl der signifikanten Stellen eingegangen). In der Diskussion geht es schlicht um die Ungenauigkeit der binären Darstellung dezimaler Nachkommastellen mittels Gleitkommazahlen. Natürlich summiert sich ein Fehler auf. Aber nicht zu ein paar Zehnteln nach ein paar Schritten.

Bei seinem Code ist das größte Übel das faktorielle Wachstum von Zähler und Nenner. Da ist nach ein paar Iterationen Schluss mit lustig. Daher sollte er Zähler und Nenner nicht separat ausrechnen, sondern sich die Beziehung der Folgeglieder überlegen. Bildet man die Summe, erhält man als Ergebnis:
Code:
0.7254762501100119 (Näherung)
0.7254762501100117 (1/Math.sqrt(1.9))
Diese Differenz dürfte sich tatsächlich durch Fehlerfortpflanzung erklären lassen.
 
genau.
Das habe ich bei cos, sins, quadratwurzel etc. auch hin bekommen. Doch bei dieser Aufgabe habe ich es irgendwie falsch berechnet das Folgeglied.
Es ist ja eigentlich nur a_n+1/a_n doch irgendwas ist falsch deswegen dachte ich mir "EGAL" ich schreibe es einfach so aus 😀
Das ist/war aber ja ein Satz mit X man sieht es ja an der Fehlerfortpflanzung 🙁 echt übel!
LG
 
Mein Fehler ist beim Rechnen nicht das Rechnen sondern ich bin schon zu doof die Reihe richtig auf zu schreiben.
Wie schreibt man denn 1 - 1/2*x + 1*3/2*4*x^2 - ....
als Summe auf? Ich hatte einfach (-1)^n ((2*n-1)*x^n)/(2*n) doch das ist ja quatsch. Dann ist das 3te Glied ja nicht mehr (1*3)/(2*4)*x^2 sondern 3/4*x^2 !!!!
 
Du brauchst die Summe nicht aufschreiben, Du musst dir lediglich die Folgeglieder ansehen: was musst Du tun, um von "3/8 x^2" auf "15/48 x^3" zu kommen?
 
Als Summe wäre es, wenn ich mich jetzt nicht vertan habe:
1 + sum_{i=1}^{infty} [(-1)^i * (prod_{j=1}^i 2j-1) / (prod_{j=1}^i 2j) * x^i]
 
ja du hast jetzt in der Summe auf dem Bruchstrich das Produktzeichen benutzt!
Das ist mir vorhin bei meinem letzten Post auch erst aufgefallen das es so sein muss! das Zweite Produktzeichen kannst du aber weg lassen 🙂
Ich rechne die Sachen vorher aus wie gesagt mit den Folgegliedern dann gehen solche Aufgaben sehr einfach und effizient 🙂

wenn ich von 3/8 auf 15/48 kommen will rechne ich einfach *= 5/6 das ist ja wieder 2*n-1 und 2*n n=3 da x^n = x^3 🙂
das ganze hatte ich versucht dann aufzumultiplizieren doch das hat nicht funktioniert deswegen habe ich die 3 schleifen gemacht was total "schrecklich" ist!

LG
 
wenn ich von 3/8 auf 15/48 kommen will rechne ich einfach *= 5/6 das ist ja wieder 2*n-1 und 2*n
Genau. Wenn Du noch das x dazunimmst, erhältst Du
Code:
f(n) = -f(n-1)*x*(2(n-1)-1)/(2(n-1)), f(0)=1

Code:
f(1) = 1
f(2) = -f(1)*x*1/2 = -1/2 x
f(3) = -f(2)*x*3/4 = 1/2 x^2 * 3/4 = 3/8 x^2
f(4) = -f(3)*x*5/6 = -3/8 x^3 * 5/6 = -15/48 x^3
...
Wenn Du also das Folgeglied mit sn bezeichnest, dann kannst Du in einer Schleife ganz einfach ein neues Folgeglied berechnen und auf Deine Summe zählen.
 
😵 kann das sein das es Rekursiv leichter geht so schön wie du es dort aufgeschrieben hast 🙂 sieht es so aus!
Ich habe mich derzeit leider nicht mehr weiter um die Aufgabe gekümmert deswegen sry!
Werde heute wieder einiges an Übungen machen hoffe ich komme wieder dazu das hier mal FERTIG zu machen.
Meins läuft ja wenn man über die "Fehlerfortpflanzung" hinweg sehen würde 😀 haha! stellt man sich vor so würden die Ingeniuere arbeiten die Pilotensysteme bauen!!! *Kopfschüttel* <- soll ein Witz sein!!! nicht ernst nehmen 😉

LG
 
Naja, so schlimm sieht das iterativ jetzt auch nicht aus:
Java:
    public static double f(double x) {
        double sum = 0;
        double sn = 1;
        double n = 2;
        while (Math.abs(sn) > 1E-16) {
            sum += sn;
            sn = x*(sn/n - sn);
            n += 2;
        }
        return sum;
    }
 
😵 das hätte ich wieder viel zu umständlich gemacht 🙁 grrr.....!!!
Vielleicht schaffe ich es ja noch alleine Rekursiv 😀 doch dazu erst später okay 🙂
Nochmals DANKE 🙂 *DaumenHOCH*
 
Ich sehe grade das ich ein Problem habe wie kommst du denn auf die geniale Formel?
sn = x*(sn/n - sn);

Ich hab es nachgerechnet im dritten Schritt kommt ja raus 1/2/4 also 1/8 - 1/2 dann noch und das gibt dann 3/8 =) Wie kommt man auf sowas? Ich bin zu doof 🙁!!!
 
Das ist einfach das Ergebnis von -f(n-1)*x*(2(n-1)-1)/(2(n-1))

Hier mal eine Nebenrechnung ohne x. Ich setze mal m := n-1, damit das hier schöner zu lesen ist:
Code:
  -f(m)*(2m-1)/2m
   ^^^^^^^^^^^ ausrechnen
= -(f(m)*2m/2m - f(m)/2m)
         ^^^^^ = 1
= -(f(m) - f(m)/2m)
  ^^ ausrechnen
= -f(m) + f(m)/2m
  ^^^^^   ^^^^^^^ umstellen
= f(m)/2m - f(m)
Danach wieder mit x multiplizieren und gut ists.

Das führt im Code zunächst zu
Java:
sn = x*(sn/(2*n) - sn)
n++;

Da der Spaß in einer Schleife läuft und Multiplikation ja nur das wiederholte Anwenden der Addition ist, lasse ich n gleich um 2 hochzählen und kann damit die Multiplikation im Teiler streichen. Übrig bleibt also:
Java:
sn = x*(sn/n - sn)
n+=2;
 
😳 tut mir leid.
Aber mihe7 hat es sehr gut beantwortet und jetzt ist nicht mehr unklar 🙄

Danke nochmals für die Hilfe 😉
 

Zurück
Oben