Kettenbruch

Dr Franke Ghostwriter
hänge grade bei der aktuellen EA. Die iterative Implementierung steht:

Code:
public double werteIterativAus() {
        if(werte.length!=0) {
            double ergebnis=werte[werte.length-1];
           
            for(int i=werte.length-2;i>=0;i--) {
            ergebnis=1/ergebnis+werte[i];
            }
            return ergebnis;
        }
        return 0;
}

Bei der rekursiven Implementierung happerts allerdings. Bin für Ansätze dankbar
 
Sei k := werte.length > 0 die Anzahl der Elemente in werte.


Sei f rekursiv definiert durch:

f(0) := werte[k-1]

f(n+1) := 1/f(n) + werte[k-n-2] für 0 <= n <= k-2

Dann ist werteRekursivAus = f(k-1)

Beispiel k = 4:

werteRekursivAus
= f(3)
= 1/f(2) + werte[0]
= 1/(1/f(1) + werte[1]) + werte[0]
= 1/(1/(1/f(0) + werte[2]) + werte[1]) + werte[0]
= 1/(1/(1/werte[3] + werte[2]) + werte[1]) + werte[0]

Liebe Grüße
 
Zuletzt bearbeitet:
Meine Lösung:
Code:
 public double werteRekursivAus() {
    return werteRekursivAus(werte.length);
    }
  
    private double werteRekursivAus(int k) {
    double erg=0;
    if(k>0) {
        erg=(1/werteRekursivAus(k-1))+werte[werte.length-k];
        }
    if(k==0) {
        erg=(1/erg)+werte[k];
    }
    return erg;
    }
 
Im "if (k==0)"-Block hast Du eine Division durch 0 bei Auswertung von 1/erg, weil erg den Wert 0 hat.


Ausserdem ist die Fallunterscheidung nicht k>0 / k==0 sondern k>1 / k==1.

Ausserdem wird am "Rekursionsende" bei k==1 (bei Dir k==0) nicht werte[k] zurückgegeben, sondern werte[werte.length-1].

Meine Lösung:

double werteRekusivAus(const int k)
{
....if (0 == k)
....{
........// Semantik unklar
.......return 0;
....}
....else if (1 == k)
....{
........return werte[werte.length-1];
....}
....else
....{
........// 1 < k
...... return 1/werteRekursivAus(k-1) + werte[werte.length-k];
....}
}

double werteRekusivAus()
{
.....return werteRekusivAus(werte.length)
}

Liebe Grüße
 
Zuletzt bearbeitet:
Danke, EA endlich fertig! Anbei meine Lösung:

Code:
public class Kettenbruch {

    // die lineare Darstellung des Kettenbruchs
    private int[] werte;

    /**
    * erzeugt einen Kettenbruch aus der linearen Darstellung
    * @param werte
    */
    public Kettenbruch(int[] werte) {
        this.werte = werte;
    }
  
    /**
    * berechnet rekursiv den Wert des Kettenbruchs
    * @return den rekursiv berechneten Wert des Kettenbruchs, bei fehlenden Werten 0
    */
    public double werteRekursivAus() {
        return this.werteRekursivAus(werte.length);
    }
  
    /**
    * berechnet iterativ den Wert des Kettenbruchs
    * @return den iterativ berechneten Wert des Kettenbruchs, bei fehlenden Werten 0
    */
    public double werteIterativAus() {
        if(werte.length!=0) {
        double ergebnis=werte[werte.length-1];
      
        for(int i=werte.length-2;i>=0;i--) {
            ergebnis=1/ergebnis+werte[i];
            }
        return ergebnis;
        }
        return 0;
    }
  
    /**
    * approximiert den Wert der Quadratwurzel von 2 mit Hilfe der Kettenbruchdarstellung mit n Elementen
    * @param n die Anzahl der fuer die Approximation verwendeten Elemente
    * @return der approximierte Wert von Wurzel 2
    */
    public static double approximiereWurzel2(int n) {
        // TODO
      
        int[]laenge=new int[n];
        Kettenbruch aproxE=new Kettenbruch(laenge);
      
        aproxE.setWert(aproxE.berechneWurzel2Folge(n));
        return aproxE.werteIterativAus();
    }

    /**
    * approximiert den Wert der eulerschen Zahl mit Hilfe der Kettenbruchdarstellung mit n Elementen
    * @param n die Anzahl der fuer die Approximation verwendeten Elemente
    * @return der approximierte Wert fuer die eulersche Zahl
    */
    public static double approximiereE(int n) {
        // TODO
        int[]laenge=new int[n];
        Kettenbruch aproxE=new Kettenbruch(laenge);
      
        aproxE.setWert(aproxE.berechneEFolge(n));
        return aproxE.werteIterativAus();
        }

    /**
    * berechnet die Folge fuer die Kettenbruch-Darstellung der Quadratwurzel von 2 mit den ersten n Elementen
    * @param n die Anzahl der Elemente
    * @return die Folge als Array, bei n <= 0 ein leeres Array
    */
    public static int[] berechneWurzel2Folge(int n) {
        // TODO
        int[] rueck=new int[n];
        rueck[0]=1;
        for(int i=1;i<n;i++) {
            rueck[i]=2;
        }
        return rueck;
    }
  
    /**
    * berechnet die Folge fuer die Kettenbruch-Darstellung der eulerschen Zahl mit den ersten n Elementen
    * @param n die Anzahl der Elemente
    * @return die Folge als Array,  bei n <= 0 ein leeres Array
    */
    public static int[] berechneEFolge(int n) {
        // TODO
        int[] rueck=new int[n];
        int e=2;
        rueck[0]=2;
      
        if (n>1) {
            for(int i=1;i<n;i++) {
            if((i+1)%3==0) {
                rueck[i]=e;
                e+=2;
            }
            else {
                rueck[i]=1;
            }
            }
        }
        return rueck;
    }
  
    private double werteRekursivAus(int k) {
        double erg=0;  
      
        if(k<=0) {
        return 0;
        }
      
        if(k>0) {
        erg=(1/this.werteRekursivAus(k-1))+werte[werte.length-k];
            }
        if(k==1 && erg!=0) {
        erg=(1/erg)+werte[werte.length-1];
        }
        return erg;
    }
  
    public void setWert (int[] array) {
        this.werte=array;
    }
  
    public int[] getWert() {
        return this.werte;
    }

}
 
Deine werteRekursivAus(int k) Lösung entspricht nicht meiner in Beitrag #4 und ist immer noch falsch.
If Falle k == 1 passieren zwei schreckliche Dinge:
1. Eine Division durch 0 weil 1/werteRekusivAus(1-1) = 1/werteRekusivAus(0) = 1/0 ist
2. werte[werte.length-1] wird zweimal addiert, einmal im k>0 Block und dann nochmal im k==1 Block.

Liebe Grüße
 
Zuletzt bearbeitet:
Oben