Hi Leute,
ich hoffe das ihr mir helfen könnt.
Es geht um die angehängte Aufgabe..
Es soll eine Reihe Programmiert werden um den natürlichen Logarithmus zu
berechnen. Die Potenzfunktionen wie pow sind nicht erlaubt.
Leider komme ich nicht auf die richtige bzw erwartete Ausgabe des
Programmes..
Mein Ansatz :
#include<stdio.h>
int main()
{
double x, summand1=0, summand2=0; summe_neu=0, summe_alt;
int k;
printf("Bitte geben das Argument x eingeben\n");
scanf("%lf",&x);
if(x<=0)
{ printf("Ungueltiger Wert, Porgramm abbruch!\n");
return 1;
}
do
{ k=1; k+=2;
summand1+=1/(2*k+1);
summand2+=(x-1)/(x+1)*(x-1)/(x+1)*(x-1)/(x+1);
summe_neu=summand1*summand2;
summe_neu=summe_alt;
}
while(summe_neu!=summe_alt);
printf("ln(%lf)=%.9lf",x,2*summe_neu);
return 0;
}
Hallo,
dein Fehler scheint in der Summenbildung zu liegen.
Stephan schrieb:> summand2+=(x-1)/(x+1)*(x-1)/(x+1)*(x-1)/(x+1);
Damit bildest du ja immer ((x+1)/(x-1))^3
Stattdessen müsste die Formel lauten:
1
intexp=1;
2
summand2=1;
3
4
for(exp=1;exp<k+1;exp++)//Dies ist ((x+1)/(x-1))^(2*k+1)
Ich würde dir empfehlen die ersten zwei Iterationen einfach mal ohne
Schleife aufzuschreiben, dann siehst Du eventuell wo Werte inkrementiert
und wo Werte verglichen werden müssen.
Und wenn pow() nicht erlaubt ist, dann würde ich mir ganz fix eine
eigene Funktion schreiben um Potenzen zu berechnen. Oder ist das auch
verboten?
Jemand schrieb:> Und wenn pow() nicht erlaubt ist, dann würde ich mir ganz fix eine> eigene Funktion schreiben um Potenzen zu berechnen. Oder ist das auch> verboten?
Eine Funktion zu schreiben ist leider nur dann erlaubt wenn es in der
Aufgabenstellung gefordert ist.
Danke für den Tipp, das probiere ich jetzt mal aus!
Deine Schleife stimmt hinten und vorne nicht, soweit ich das überblicke.
Du initialisierst k=1 jedesmal neu am Schleifenanfang.
Außerdem addierst du jeweils (x-1/x+1)^3 zu summand2. Wobei summand1
und summand2 eigentlich Faktoren sind.
Die Aufgabe ist außerdem falsch gestellt, da die erste Reihe bei k=0
anfängt und die Summenformel mit k=1.
Jemand schrieb:> Und wenn pow() nicht erlaubt ist, dann würde ich mir ganz fix eine> eigene Funktion schreiben um Potenzen zu berechnen. Oder ist das auch> verboten?
Eine eigene Potenzfunktion zu schreiben ist Zeitverschwendung und
beinhaltet eine zusätzliche Fehlerquelle.
Für ein gegebenes Argument x wächst die Potenzkomponente mit dem
konstanten Faktor
[ (x-1)/(x+1) ]^2.
Den muss man nur einmal ausrechnen und dann immer mit dem laufenden
Potenzglied multiplizieren.
Eine Potenzfunktion ist hier nicht erforderlich.
Jemand schrieb:> Und wenn pow() nicht erlaubt ist, dann würde ich mir ganz fix eine> eigene Funktion schreiben um Potenzen zu berechnen.
Was aus Sicht der Performance so ziemlich das schlechteste ist was man
machen kann.
Dabei ist die Reihenentwicklung doch schon angegeben, und die Basis
unter dem Exponent ist konstant und nicht von k abhängig.
Was mir bei der AUfgabe besonders schwer fällt, ist das der Exponent mit
((x+1)/(x-1))^3, ((x+1)/(x-1))^5,((x+1)/(x-1))^7 usw wächst..
Also mit k=k+2, das habe ich nämlich auch falsch gemacht wie eich gerade
sehe
Make it run first, before you make it run fast...
Persönlich finde ich es immer etwas einfacher, wenn ich Dinge
schrittweise entwickle. Der Fragesteller hat ja offensichtlich
Schwierigkeiten die Gleichung in Code zu gießen.
Und in solchen Fällen hilft es mir immer wenn ich irgendwo a^b lese,
dann schreibe ich an der Stelle einfach pow(a,b). Sobald das Programm
richtig rechnet kann ich Überlegungen anstellen, wie man den Code
eventuell optimieren kann.
>Eine Funktion zu schreiben ist leider nur dann erlaubt wenn es in der>Aufgabenstellung gefordert ist.>Danke für den Tipp, das probiere ich jetzt mal aus!
Was ein Unsinn. Man darf einer der wichtigsten Programmmiermethoden
(Auslagerung und Aufteilung von Lösungen) nicht verwenden.
Und den Still eignet man sich dann an, schönen alles scriptmässig in
einen block knallen.
manoman
Gruß J
jb schrieb:> Was ein Unsinn. Man darf einer der wichtigsten Programmmiermethoden> (Auslagerung und Aufteilung von Lösungen) nicht verwenden.
Es gibt in der Klausur Aufgaben wo man dann Funktionen schreiben muss
und Aufgaben wo es nicht erlaubt ist..
jb schrieb:> Was ein Unsinn.
Kein Unsinn, sondern der Hinweis wie man sowas effizient programmiert.
Jemand schrieb:> Make it run first, before you make it run fast...
Im Prinzip nicht verkehrt, führt hier aber zu einem völlig falschen
Ansatz.
@Stephan:
Mach dir klar, dass jeder neu Summand der Reihe aus zwei Faktoren
besteht.
Der erste ist von k abhängig 1/(1k+1) und muss immer berechnet werden.
Der Zweite Faktor lässt sich aber durch einfache Multiplikation vom
vorigen Reihenelement berechnen. Du musst dir also nur das Ergebnis der
vorherigen Iteration merken und kannst das dasmit dem konstanten Faktor
((x-1)/(x+1))² multiplizieren.
Stephan schrieb:> Es geht um die angehängte Aufgabe..
Die Aufgabenstellung ist sowieso einfach nur falsch. Die Summe wird
natürlich ab k=0 gebildet, sonst fehlt der erste Summand.
Sowas als Aufgabe zu definieren ist schon echt kriminell.
Georg
Ein weiterer Fehler:
> 1/(2*k+1)
Dieser Ausdruck ist für k>0 immer 0, da hier zwei int-Werte dividiert
werden. Mindestens einer der Operanden muss double sein, damit auch die
Division in double ausgeführt wird.
Also:
1.0 / (2*k+1)
oder
1 / (double)(2*k+1)
oder
1.0 / (double)(2*k+1)
Yalu X. schrieb:> Mindestens einer der Operanden muss double sein, damit auch die> Division in double ausgeführt wird.
Steht doch auch in der Aufgabenstellung (Bild) drin.
> "Alle Gleitpunkt-Datentypen sollen vom Typ double sein"
Der Andere schrieb:> Der Zweite Faktor lässt sich aber durch einfache Multiplikation vom> vorigen Reihenelement berechnen. Du musst dir also nur das Ergebnis der> vorherigen Iteration merken und kannst das dasmit dem konstanten Faktor> ((x-1)/(x+1))² multiplizieren.
Was ich oben schon schrieb...
Erwin D. schrieb:> Yalu X. schrieb:>> Mindestens einer der Operanden muss double sein, damit auch die>> Division in double ausgeführt wird.>> Steht doch auch in der Aufgabenstellung (Bild) drin.>> "Alle Gleitpunkt-Datentypen sollen vom Typ double sein"
Ja. Dass man aber Nicht-Gleitpunkt-Datentypen ggf. explizit konvertieren
muss, steht da nicht drin (dafür aber in einem C-Buch).
Stephan schrieb:> Leider komme ich nicht auf die richtige bzw erwartete Ausgabe des> Programmes..
Das kannst du auch nicht. Die Tayloreentwicklung ist fehlerhaft :-(
Richtig siehe Anhang. Es muss jeweils 2k-1 in der Gleichung stehen!
Yalu X. schrieb:> Ja. Dass man aber Nicht-Gleitpunkt-Datentypen ggf. explizit konvertieren> muss, steht da nicht drin (dafür aber in einem C-Buch).
Stimmt :-)
Stephan schrieb:> Leider komme ich nicht auf die richtige bzw erwartete Ausgabe des> Programmes..>> Mein Ansatz :>> #include<stdio.h>>> int main()> {
Ja. Glaub ich unbesehen. Zu allererst mal int main (void) { hinschreiben
und sich dabei denken, nach der Gesachweiften wird mir schon was
einfallen.
Also, du gehst schlichtweg völlig unmathematisch und unsystematisch an
die Aufgabe heran.
Mein Rat:
1. Laß am Anfang das Formulieren in irgend einer Programmiersprache
bleiben.
2. Denke darüber nach, wie sich die Sache in eine sequentiell
abarbeitbare Reihe entwickeln läßt, also wie der Beitrag N sich aus dem
vorherigen Beitrag N-1 entwickeln läßt.
3. Setze deine Startumgebung, also hier zum Beispiel (falls die Reihe
richtig vorgegeben sein sollte)
a = (x-1)/(x+1) und b = a * a und Ergebnis = 0
4. jetzt kannst du dir nen PAP malen oder ein Struktogramm und hast
damit bereits die fertige Lösung
5. anschließend kannst du das in eine konkrete Programmiersprache
fassen.
W.S.
Da Du weiterhin Probleme mit der Schleife hast, kannst Du ja erstmal ein
programm schreiben, welches folgendes berechnet:
Das ist prinzipiell genau das gleiche wie deine Aufgabe, nur alles
"komplizierte" wurde entfernt.
Und ein Hinweis wurde hier ja schon genannt:
schreibe statt 1/(2*k+1) lieber 1.0/(2.0*k+1.0).
So ist auf jeden Fall sichergestellt, dass Du keine Integerdivision
durchführst.
Tasg schrieb:> Und wie kommst du auf die Summen für ln(1-z) oder ln(1+z)
durch Reihenentwicklung
> Ausserdem enthält die Herleitung Fehler..
wo?
Stimmt, bei der Quotientenbildung muss es ln(1+z)-ln(1-z) heißen :-(
Ist durch copy and paste entstanden
Warnmeldungen des Compilers einschalten und die ausgegebenen Warnungen
nicht ignorieren, bspw. in
1
scanf("%lf",x);
Interessanterweise war das in deiner ersten Version noch richtig.
Außerdem: Versuch dich zu konzentrieren, oder mach mal eine längere
Pause :)
1
k=1;k=k+2;
Das wurde schon angemerkt. Wieso steht die Initialisierung von k in
der Schleife und nicht außerhalt? Und wieso wird k in jedem
Schleifendurchlauf um 2 erhöht und nicht um 1? Und wieso passiert das
gleich am Anfang der Schleife? Wie groß muss k zur Berechnung des ersten
Summanden sein? Bei dir ist es 3, was überhaupt nicht stimmen kann.
1
mult1+=1/(2*k+1);
Der Compiler sagt (mit Recht), dass hier mult1 möglicherweise
uninitialisiert verwendet wird.
Aber wieso überhaupt += und nicht =? Addiert wird doch erst, nachdem
mult1 und mult2 miteinander multipliziert sind, was aber erst weiter
unten passiert. Und der Fehler mit der Integer-Division ist immer noch
da.
1
mult2=(x-1)/(x+2);
Wo kommt das x+2 her?
1
for(i=1;i<=k+2;i=i+2)
Wieviele Schleifendurchläufe erwartest du, und wie oft dreht die
For-Schleife tatsächlich?
1
exp*=(x-1)*(x+1);
Die Variable exp wird oben mit 0 initialisiert. Wie oft musst du 0 mit
einer anderen Zahl multiplizieren, damit ein von 0 verschiedenes
Ergebnis herauskommt? Und wieso werden (x-1) und (x+1) hier plötzlich
multipliziert und nicht dividiert?
1
summe_neu=mult1*mult2;
Und wo wird hier jetzt etwas aufsummiert? summe_neu wird in jedem
Schleifendurchlauf überschrieben, die bisherigen Berechnungen gehen
dabei verloren. Schade um die Rechenzeit :)
Meine dringendste Empfehlung: Schlaf mal eine Nacht darüber und
versuch's morgen in alter Frische noch einmal!
Da die Summanden sehr schnell recht klein werden können, kann es sein
dass sich der PC einen Wolf rechnet ohne das der berechnete Wert
nennenswert genauer wird. Wenn man Pech hat beendet der Compiler dann
irgendwann das Spielchen, ohne dass das Programm zum Ende gekommen ist.
Daher besser sowas:
1
while(fabs(sum_alt-sum)>delta)
Jetzt würde nur noch so lange gerechnet bis die Differenz kleiner einem
bestimmten Wert ist.
Gruselfrosch schrieb:> Wenn man Pech hat beendet der Compiler dann> irgendwann das Spielchen, ohne dass das Programm zum Ende gekommen ist.
Wieso Pech? Ist eine Endlosschleife des Programmierers höchstes Glück?
So eine Art Software mit Ewigkeitsanspruch?
Georg
Sie sollen diese Projektaufgaben selbstständig bearbeiten und lösen. Alle Lösungen, die aus der Betrachtung des Quellcodes und dem Vergleich mit anderen abgegeben Lösungen vermuten lassen, dass die Bearbeitung nicht eigenständig durch Sie selbst erfolgte, werden mit 0 Punkten bewertet oder zumindest stark abgewertet. Diese Abwertung betrifft auch diejenigen Lösungen, die als Quelle für andere abgegebene Lösungen vermutet werden
Julian Lindemeyer schrieb:> Hallo> Habe. Probleme bei dieser Aufgabe und bräuchte einen Ansatz der mir> fehlt
Das kommt mir irgendwie bekannt vor.
Und irgendwie ist auch schon alles dazu schon gesagt.
hi
ich bins nochmal
hab mal versucht was zu machen aber die Ergebnisse stimmen nicht ganz
und ich hab noch das Problem das ich iterationsschritte mitzählen soll
Brauch ich dafür noch eine schleife?
Wie viele Threadleichen möchtest du noch ausgraben dafür?
Das allermindeste, was du tun solltest, ist dir wenigstens mal den von
dir gekaperten Thread durchlesen - daraus kannst du schon noch was
lernen. Und nein, eine Potenzreihe entwickelt man ganz gewiss nicht,
indem man das erste bis N-te Glied linear in eine einzige Formel
schreibt, sondern man entwickelt die einzelnen Summanden Stück für
Stück. Das solltest du allerdings spätestens nach dem Lesen des
Threads verstanden haben.
Danach kannst du dann noch an deinem Verständnis für Aufgabenstellungen
arbeiten, denn darin sind relativ strikte Regeln festgelegt, in welcher
Form du was machen sollst (bspw. keine impliziten Initialisierungen von
Variablen direkt in der Definition).
Damit darf dieser Thread wieder in die Threadleichenkiste.