Schleifenprogramm erstellen
-
Hallo Zusammen,
bin neu hier im Forum und auch in der Programmierszene
Ich habe ein Problem und zwar soll ich eine Schleife zur Berechnung der Reiheschreiben mit dem Endkriterium=Anzahl der Schleifendurchläufe n.Dabei darf man keine mathematischen Funktionen benutzen.
Grübel jetzt schon länger darauf rum und bin echt am verzweifeln, da ich echt nicht weiß wie ich anfangen soll.Ich möchte die Aufgabe auch nicht gemacht bekommen, sondern ich hoffe ich kann die Aufgabe mit ein wenig Unterstützung von euch lösen.
Mein Ansatz wäre jetzt erstmal irgndwie Gesetzte für die Folgeelemente festzulegen, sowie für die Teilsummenbildung und die Anweisung.
Dabei hapert es allerdings schon...leider.Hoffe auf einen kleinen Denkanstoß.
mfg
Stormtroop@
-
Ist zwar kein C++, aber so ungefähr müßte es gehen.
potenz=1 for i=1 to m summe+=potenz potent*=0.5
-
Darfst du den mathematischen Term umformen in eine geschlossene Form (*hustgeometrischereihehust*)?
Wenn nicht: Wie könnte man denn eine Aufsummierung im Quellcode darstellen? Vielleicht könnte man eine Variable für die bisher erreichte Zwischensumme nehmen und auf diese immer den aktuellen Folgenwert addieren...
-
Michael E. schrieb:
Darfst du den mathematischen Term umformen in eine geschlossene Form (*hustgeometrischereihehust*)?
Das hilt nicht wirklich, weil er kein std::pow für summe=2-pow(2,-m) oder so benutzen darf.
-
volkard schrieb:
Das hilt nicht wirklich, weil er kein std::pow für summe=2-pow(2,-m) oder so benutzen darf.
Stimmt, mein Fehler.
-
Das Einfachste wäre natürlich
double GetSolution() {return 2.0;}Nötig wäre es, eine eigene Pow-Funktion zu schreiben und die Werte in einer Schleife zu addieren.
Eine mögliche Lösung ist hier, du kannst es aber erst einmal selber probieren.Edit: Start war bei m=1 statt m=0
-
1*(1-q^(n+1))/(1-q) =
1/2 * (1-(1/2)^(n+1)) =
1/2 - 1/(2^(n+1))2^n lässt sich in C++ mit 2<<n berechnen.
Also der Code:double result=.5-1./(2<<(n+1));
-
Nun ich würde mal ganz einfach sagen (Pseudocode):
Ohne rumtricksen:
Result = 0 for m=0 to n tmpValue = 1 for i=0 to m tmpValue = tmpValue * 0.5 end loop add tmpValue to Result end loopMit Formel bearbeiten:
tmpValue = 1 for i=0 to n-1 tmpValue = tmpValue * 0.5 end loop Result = 2 - tmpValue
-
Vicious Falcon und kenpow haben beide die falsche Lösung gepostet.
Richtig ausmultipluziert heisst die getrickste Version nämlichdouble result=2 - 1./(2<<(n+1));Das entspricht natürlich im Wesentlichen der Version von wxSkip.
-
Im Wesentlichen heisst, dass die wxSkip auch gefailt hat.
-
fail schrieb:
Im Wesentlichen heisst, dass die wxSkip auch gefailt hat.
??
1. Syntax?
2. Semantik?
-
Okay, ich habe bei m=1 statt m=0 angefangen.
fail schrieb:
double result=2 - 1./(2<<(n+1));int n = 0; result=2 - 1./(2<<(n+1)); assert(result==1.0); n=1; result=2 - 1./(2<<(n+1)); assert(result==1.5);
-
Gemeint war Semantik. Ich habe "for i=0 to n-1" als "von i=0 bis zu (exklusiv) n-1" aufgefasst.
Was Standard ist, weiss ich nicht.
-
fail schrieb:
Gemeint war Semantik. Ich habe "for i=0 to n-1" als "von i=0 bis zu (exklusiv) n-1" aufgefasst.
Was Standard ist, weiss ich nicht.Und ich habe inklusiv gemeint (hab extra nochmal drüber nachgedacht).
Mit Syntax? und Semantik? habe ich gemeint, dass ich sowohl die Syntax als auch die Semantik deiner Aussage nicht verstehe. (die Syntax vielleicht zum Teil, aber sie war einfach grauenhaft (z.B. die wxSkip
))
-
Stormtroop@ schrieb:
Hallo Zusammen,
bin neu hier im Forum und auch in der Programmierszene
Ich habe ein Problem und zwar soll ich eine Schleife zur Berechnung der Reihem=∞
∑ 1/2^m
m=0Die einfachste Lösung sind zwei verschachtelte Schleifen, die äußere Summiert über die 0.5^m und die innere Schleife rechnet jeweils 0.5^m aus, durch triviale Multiplikation von 0.5 mit sich selbst.
Da es eh schon Lösungen gab, die kompakte Variante. Noch eine Schleife außen herum, damit man die Konvergenz der Reihe sieht.
#include <iostream> int main () { double sum = 0.0L, prod; int max = 20; // Abbruchkriterium for (int j=1; j != max; ++j) { sum = 1.0L; // 0.5^0 == 1.0 for (int m = 1; m != j; ++m) { prod = 0.5L; for (int i = 1; i != m; ++i) { prod *= 0.5L; } sum += prod; } std::cout << sum << std::endl; } }
-
Und hier noch mal eine korrekte Version (für n <= 30) mit kurzer
Test-main() zur Kontrolle.
Stand hier schon mal, aber ist wohl im @Daten-Nirvana verschollen.double BerechneReihe(unsigned n){ /* n == Anzahl Durchgaenge */ unsigned i, t, m = 0; double Result = 1.0; while(m++ < n){ i = 0; t = 2; while(++i < m) t <<= 1; Result += 1.0 / (double) t; } return Result; } #include <stdio.h> /* Oder (wenn man mehr Schreibarbeit vorzieht): #include <cstdio> using namespace std; */ #define MAX_ANZAHL_DURCHGAENGE 16 int main(){ unsigned i = 0; do{ printf("Resultat (n == %d): %g \n", i, BerechneReihe(i)); }while(++i < MAX_ANZAHL_DURCHGAENGE); getchar(); return 0; }Ausgabe (zur Kontrolle):
Resultat (n == 0): 1 Resultat (n == 1): 1.5 Resultat (n == 2): 1.75 Resultat (n == 3): 1.875 Resultat (n == 4): 1.9375 Resultat (n == 5): 1.96875 Resultat (n == 6): 1.98438 Resultat (n == 7): 1.99219 Resultat (n == 8): 1.99609 Resultat (n == 9): 1.99805 Resultat (n == 10): 1.99902 Resultat (n == 11): 1.99951 Resultat (n == 12): 1.99976 Resultat (n == 13): 1.99988 Resultat (n == 14): 1.99994 Resultat (n == 15): 1.99997(@Themenstarter)
Falls n > 30 sein soll, definiert man t als double und ersetzt die
Zeilet <<= 1;durch
t *= 2.0;.
(@john)
Im Sinne einer Modularisierung trennt man auch lieber die eigentliche
Berechnungs-Funktion von der Ausgabe, anstatt dass man alles in eine dreifach
verschachtelte Schleife packt, oder ist so eine Vorgangsweise in C++
eher unüblich?)
(@Daten-Nirvana)
Bitte nicht wieder löschen. (Oder sind korrekte Lösungsvorschläge hier generell nicht erwünscht?)MFG
-
hallo Zusammen,
Vielen vielen Dank für die Antworten.Habe bevor ich nochmal hier ereingeschaut habe mal selber was rumprobiert.Das ist bei rumgekommen:Allerdings läuft das mit dem Exponenten nicht so wirklich.Wie schreibt man das in C++?
Zu den unzähligen Lösungen hier: Vielen Dank, nur leider versteh ich vieles davon einfach nciht, weil wir noch nicht soviel gehabt haben.
Das letzte was wir gelernt haben waren If-Else Bedingungen.Hoffe ihr könntet mal drüberschaun.
Ich habe es auch einmal mit #include <math.h> und dann pow() probiert.Damit geht das wunderbar, nur leider soll ich das vermeiden.mfg
Stormi
-
Nutze doch bitte <cpp> </cpp> (statt "<>" --> "[]") um Code herum ... und nutze Einrückung - das fördert die Hilfsbereitschaft der User.
Wenn du Variablen hast die sich nicht ändern werden ist
const(== ändert sich nicht) dein Freund. Schleifen laufen meist vonint i=0; i< irgendwas; ++i- dass sie bei 0 starten hat oft was mit Arrays zu tun .. wenn du von 0 bis <=irgendwas zählst hast du (irgendwas+1) Durchläufe also einer mehr als gewünscht. Wenn du double initialisierst gewöhn dir an gleich ein .0 dranzuhängen und nutz immer "sprechende" Namen, der Code wird dadurch übersichtlicher. Variablen solltest du so spät wie möglich einführen und nur so lange wie nötig im Scope halten. Das was nicht tu kann was mit den genutzten Typen und impliziter konvertierung zu tun haben:int main () { int eingabe =0; printf("Bitte die Anzahl der Schleifendurchläufe eingeben: "); scanf("%i",&eingabe); // int m = 0; // brauchen wir nur in der Schleife // double n = 0; // sprechende Namen double ergebnis = 0.0; const double zaehler = 1.0; // const double nenner = 2.0; // wo benutzt du den? for(int m = 0; m < eingabe; m++) { // typen: // double += double / (int SHIFTOP int) // double += double / (int) ergebnis += zaehler / (2<<(m)); // ergebnis += zaehler / double(2<<m); printf("%lg\n", ergebnis); } }so und nun teste mal was rauskommst wenn du
double = double / 2;ausgibst und lies die ersten 2 Abschnitte von http://www.cplusplus.com/doc/tutorial/typecasting/
-
Stormtroop@ schrieb:
Ich habe es auch einmal mit #include <math.h> und dann pow() probiert.Damit geht das wunderbar, nur leider soll ich das vermeiden.
Wenn du mit pow() auf die richtige Lösung kommst, was spricht dagegen, eine eigene pow-Fkt. zu schreiben?
Wenn der Exponent eine Ganzzahl ist, ist es auch nicht schwierig. Anders sähe es aus, wenn der Exponent ebenfalls ein double wäre.double MyPow(double base, int e) { if(!e) // der Exponent ist Null, das Ergebnis ist durch Definition 1 return 1.0; double ret=1.0; // hier wird der Returnwert deklariert und mit 1 initialisiert for(int i=1;i<=e;++i) // in einer Schleife von 1 bis einschließlich e ret*=base; // in jedem Durchgang ret = ret * base -> kürzere Schreibweise: ret*=base; return ret; // Ergebnis liefern }Bei einem Aufruf MyPow(2.0, 5) sieht es entrollt so aus (Pseudocode)
e>0?weiter:sonst 1.0 zurückliefern Returnwert mit 1.0 initialisieren -> entspricht 2[h]0[/h] schleife: für i = 1 bis i=e Returnwert jeweils mit base multiplizieren Returnwert zurückgeben -> ret*=base: 2.0 ,i ist 1 ret*=base: 4.0 ,i ist 2 ret*=base: 8.0 ,i ist 3 ret*=base: 16.0 ,i ist 4 ret*=base: 32.0 ,i ist 5 hier ist i==e und die Schleife wird beendetEdit: Eine mögliche Lösung ist hier.
-
Was spricht gegen folgendes ?
#include <iostream> using namespace std; int main() { double summe = 0; const double z = 1.0; int m = 0; cout << "m = "; cin >> m; for(int i=0; i<=m; ++i) { int tmp = ( 1<<i ); summe += ( z/tmp ); } cout << summe; cin.get(); return 0; }lg dweb