• Hallo Besucher!

    Du bist neu im Forum? Dann registriere dich hier, um Diskussionen beizutreten oder eigene Themen zu erstellen. Für die Registrierung ist es erforderlich, dass du einen Spielaccount bei Die Stämme hast.

    Andernfalls kannst du dich hier direkt einloggen.

    Falls du dein Passwort vergessen hast, kannst du hier ein neues Passwort anfordern.

Java: Eulerreihe

DeletedUser32388

Gast
Hallo ihr lieben Menschen!
Ich studiere Wirtschaftsinformatik im ersten Semster und habe eine Hausarbeit bis Mittwoch zu tätigen, die mir leider etwas zu schaffen macht.

Die Aufgabe lautet:
"Die Reihe der Eulerschen Zahl. Programmieren Sie die Methode eulerreihe, welche den Grenzwert der geometrischen Reihe (siehe Abbildung) bestimmt. Implementieren Sie dazu eine Schleife, die solange die Fakultät im Nenner zum bisherigen Ergebnis dazu addiert, bis das Resultat (als double) sich nicht mehr ändert."


Da ich noch nicht viel Erahrungen mit do-while- und for-Schleifen habe, möchte ich nach Möglichkeit nur if-Schleifen benutzen.
//Edit: Wenn euch for-Schleifen hierbei sinnvoller erscheinen, nehm ich diese auch gerne ;)
Mein erster Gedanke war, dass zunächst zu überprüfen ist, ob die Ergebnisse übereinanderstimmen, also muss als Argument lauten neu!=alt. Danach habe ich ehrlich gesagt keine wirklich produktiven Ideen gehabt wie ich die Eulersche Zahl mit einer Fakultät darstellen könnte.

Hier ein Anfang meines bisherigen Codes:

Code:
	{ 	
		double neu = 0;
		double n = 1.0;
		double fakultaet = (n*(n+1));
		double alt = 0;
		
			{if (alt != neu)
				{neu = alt; 
				alt = 1 +  1/1  +  1.0/fakultaet;n++;
				}
			}
			return alt;

		
	
	}

Bin mir auch irgendwie sicher, dass der Nenner falsch beschrieben wurde von mir, aber ich hoffe, dass mir jemand weiterhelfen kann...

LG Kevin
 
Zuletzt bearbeitet von einem Moderator:

DeletedUser

Gast
Um zu prüfen ab der wievielten Addition des Kehrwerts der Fakultät das Ergebnis sich e annähert kannst du folgenden Code von mir benutzen:

PHP:
public class EulerscheZahl {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) {
		//Deklaration
		double erg = 0,fak,differenz;
		int n = 99; //Beliebige Zahl, je höher desto stärker sollte sich das berechnete e der Konstante der Math-Klasse annähern!
		//Verarbeitung
		for(int i = 0;i<=n;i++){
			fak = 1;
			for(int j = i;j>0;j--){
				fak *= j;
			}
			erg += 1/fak;
		}
		differenz = erg-Math.E;
		//Ausgabe
		System.out.println("Das Ergebnis lautet: \t\t" + erg);
		System.out.println("Die Eulersche Zahl lautet: \t" + Math.E);
		System.out.println("Die Differenz beträgt: \t\t" + Math.abs(differenz));
	}

}

Damit hast du schon einmal die Möglichkeit, zu überprüfen wie schnell es sich der Konstante annähert (Ab n = 17 ist bereits die minimale Differenz erreicht, nämlich von nur 4.440892098500626x10^-16), bei einer genaueren Bestimmung müsstest du dir einen genaueren e-Wert aus dem Netz saugen.

Ich hoffe ich konnte dir damit zumindest ein Stück weiterhelfen.

Gruß
 

DeletedUser32388

Gast
Hey,
vielen Dank für Deine Hilfe!
Das hat mir einige Last von den Schultern genommen, nachdem ich mir gestern noch den Kopf darüber zerbrechen musste. Habe mir auch die for-Schleifen nochmal genau angesehen, sodass ich letztlich auch alles nachvollziehen und heute eine korrekt Lösung einreichen konnte. :)

Hier die korrekte Lösung (bzw. Methode) zur Aufgabe:
PHP:
	public double eulerreihe() {
		
        double erg = 0, erg2 = erg,fak;
        int n = 99;
        for(int i = 0;i<=n;i++){
            fak = 1;
            for(int j = i;j>0;j--){
                fak *= j;
            }
            erg += 1/fak;
            if (erg == erg2) break;
            } 	
        return erg;}

Liebe Grüße
Kevin
 

DeletedUser

Gast
Obwohl es funktioniert ist es schechter Programmierstil eine iterative Schleife "mit Gewalt" abzubrechen.

Genau deswegen gibt es Konstrukte wie "while - do" o.Ä...
 

DeletedUser32388

Gast
Danke für das Feedback!
Mir ist in dem Moment leider nicht in den Sinn gekommen wie ich wieder aus der Schleife hätte rauskommen können, da ich noch nicht viel mit den von dir erwähnten Konstrukten praktiziert habe und mir somit die Erfahrung fehlt.
Würde mich freuen, wenn Du oder jemand anders einen alternativen Lösungsvorschlag zeigen könntest.

Gruß
 

DeletedUser

Gast
Ich habe schon lange nicht mehr programmiert und kenne die Java-Syntax nicht genau.

Aber da Du schon "While - Do" erwähnt hast:

1. den Variablen vorab Werte zuweisen
(manchmal geht es auch ohne aber das ist zum einen eine grosse Fehlerquelle und auch unsauber!)

2. dann (sinngemäss!) "While (erg=!erg2)" ..."Berechnung" ..."do"
(alternativ auch "While (erg-erg2>Epsilon)" oder andere Vergleiche)

Ebenso gibt es wahrscheinlich auch in Java die "do-while" Schleife bei der die Abbruchbedingung erst am Ende geprüft wird.
Das hat den Vorteil dass den Variablen schon am Anfang per Berechnung ein Wert zugewiesen wird und nicht per Definition (wobei ich Variablen mit undefiniertem Inhalt immer gescheut habe, bei grösseren Projekten verliert man schnell die Übersicht und baut sich so unbemerkt Fehler ein...)

Also: Syntax-Buch aufschlagen und nachlesen! ;)
 

DeletedUser

Gast
PHP:
public double eulerreihe() {
        
        double erg, erg2 = 0,fak;
        while(erg != erg2) {

            fak = 1;
            for(int j = i;j>0;j--){
                fak *= j;
            }
            erg += 1/fak;
        return erg;}

Wäre wohl das korrekteste... Syntaxfehler vorbehalten, habs jetzt nicht extra ausgeführt...

so fällt auf jeden Fall auch das n = 99 weg, was ja eigentlich ein "Fehler" in der Lösung war, da nicht geprüft wurde bis erg = erg2, sonder ob erg = erg2 ODER n > 99.

Die Gefahr hierbei ist jedoch in einer Endlosschleife zu landen, falls die Berechnung so nicht "klappt"
 
Zuletzt bearbeitet von einem Moderator:

DeletedUser

Gast
Oben sind gleich 2 Fehler drin:

1. da sowohl erg wie auch erg2 mit 0 initialisiert werden bricht obige while-Schleife gleich zu Beginn ab.
2. erg2 wird gar nicht benutzt
 

DeletedUser

Gast
Ahhh... Miserabel...

Kommt davon, wenn man nur husch husch umschreibt.

PHP:
public static double eulerreihe2() {
        
        double erg = 0, erg2 = erg,fak;
        int i = 0;
        do {

            fak = 1;
            for(int j = i;j>0;j--){
                fak *= j;
            }
            erg += 1/fak;
            i++;
        } while(erg != erg2 && i < 99);
        return erg;
}

funktioniert und ist getestet, aber das Grundproblem wegen dem nutzlosen erg2 ist nicht gelöst. Das könnte man eigentlich weglassen. Ich habe es jetzt jedoch drin gelassen, weil es im vorigen beispiel auch drin war.

PHP:
if (erg == erg2) break;

war jedoch auch da schon überflüssig, weil die schleife auf jeden Fall 99 mal durchlaufen wurde, da auch da erg2 nie geändert wurde...
 

DeletedUser

Gast
In ANSI-C (jaaa... Steinzeit...) konnte man Variablenwerte in einem Befehl tauschen, aber seitdem nicht mehr (und zwar zu recht!!!).

Aber für diese Euler-Reihe muss irgendwie der letzte Wert mit dem neuen Wert verglichen werden.

Zu Argumentationszwecken nehme ich an dass es einen Datentyp "double long" gibt welcher doppelt so "lang" ist wie "double"

Dann könnte man -ohne erg2!- testen ob der auf "nur double" _gerundete_ "double long" Wert gleich dem trunc (=abgeschnittenen) "double" Wert ist um dann die "do-while"-Schleife abzubrechen.

Da oben erg2 immer noch nicht berechnet wird ist die Bedingung "erg != erg2" immer "true" und somit unerheblich...
 
Zuletzt bearbeitet von einem Moderator:

DeletedUser

Gast
Ich wollte ja nicht behaupten, dass ein test ohne erg2 möglich ist, ich habe lediglich gesagt, dass erg2 in beiden beispielen "überflüssig" ist, da ein leerer Wert, bzw 0 geprüft wird.

Eine "korrekte" Lösung wäre so, die auch nach 19 durchläufen zum Ergebnis führt.
PHP:
public static double eulerreihe2() {
        
    double erg = 0, erg2 ,fak;
    int i = 0;
    do {
        erg2 = erg;    
        fak = 1;
        for(int j = i;j>0;j--){
            fak *= j;
        }
        erg += 1/fak;
        i++;
        } while(erg != erg2);
        return erg;
    }
}
 

DeletedUser

Gast
Ich kann zwar kein Java, aber das oben sieht sehr elegant und funktional aus! :p

...allerdings sollte um es ganz sauber zu machen auch noch "j" initialisiert werden...
(jaaaa, das ist ziemlich pedantisch, aber wenn ein Projekt grösser wird, kann so etwas einem schnell das Genick brechen... als Skripter wäre das OK, aber als Informatiker nicht...)
 
Zuletzt bearbeitet von einem Moderator:

DeletedUser32388

Gast
Danke für eure Hilfe!

Das mit der do-while-Schleife konnte ich Dank des Beispiels sehr gut nachvollziehen (Dank an thecain!) und es scheint auch eine durchaus schönere Lösung zu sein.
Habe gerade mal in Musterlösungen für ähnliche Aufgaben gesehen und da wurde leider auch break zum auflösen genutzt, obwohl in der Vorlesung ebenfalls erwähnt wurde, dass break möglichst vermieden werden soll, auch wenn es zur korrekten Lösung führt.
 
Oben