C++ Programm perfect number < C/C++ < Programmiersprachen < Praxis < Informatik < Vorhilfe
|
Aufgabe | Write a program perfect.cpp to test whether a given natural number n ist perfect. A number [mm] n\in \IN [/mm] is called perfect if and only if it is equal to the sum of its proper divisors, that ist, [mm] n=\summe_{}^{}k\in\IN, s.t.k
Extend the program to find all perfect numbers between 1 and n. How many perfect numbers exist in the range [1,50000]? |
Hallo Zusammen
Ich habe in Informatik die obige Aufgabe erhalten. Nun muss ich zuerst einmal anmerken, dass ich noch nie vorher Kurse im Programmieren belegt habe und die Vorlesung erst vor vier Wochen begonnen hat. Ich habe also eigentlich überhaupt kein Vorwissen und mir ist das alles vollkommen neu.
Nun habe ich also versucht dieses Programm perfect.cpp in c++ zu schreiben. Aber der Compiler gibt mir immer Fehlermeldungen. Kann sich jemand mein Programm anschauen und mir sagen wo meine Fehler liegen, und ob das Programm überhaupt ansatzweise auf das hinausläuft, was ich programmieren soll.
Hier mein programmierversuch:
#include <iostream>
int main ()
{
//input
int n=0;
int zw_summe=1;
std::cout<<"Gib alle vollkommenen Zahlen bis n=? aus";
std::cin>>n;
//Bestimmen der Variablen und Eingabe der Schleife
for(int i=n; i>1; i--) // da 1 keine vollkommene Zahl ist beginne ich erst bei i>1
{
for(int j=2;(j*j)<i ;i++) if (i%j==0) zw_summe += j+i/j;
if(zw_summe==i)
//Ausgabe der vollkommenen Zahlen
std::cout<< i << "sind vollkommene Zahlen!"<<; }
std::cout<<endl;
return 0;
}
Ich bin wirklich über jede Hilfe froh, da ich eigentlich keine Ahnung habe was ich da Programmiere.
|
|
|
|
Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)
Hallo!
Erstmal zum Konzept:
for(int j=2;(j*j)<i ;i++)
Du meinst sicher j++
for(int j=2;(j*j)<i ;i++) if (i%j==0) zw_summe += j+i/j;
Es ist sicher gut gemeint, zu jedem gefundenen Divisor gleich den Quotienten mit zu behandeln. aber da die For-Schleife den gesamten Zahlenbereich möglicher Divisoren durchläuft, würden die Quotienten auch als Divisoren gefunden werden, und wären dann doppelt in der Summe drin. Also immer nur den Divisor addieren!
Dann sollte zw_summe vor jedem Duchlauf von FOR(i... zurück gesetzt werden, denn sonst läufst du mit einem alten Wert in dieser Variablen in die Überprüfung der nächsten Zahl.
(j*j) läßt sich besser als pow(i,2) schreiben (ggf mit include math), aber das paßt schon so.
std::cout<< i << "sind vollkommene Zahlen!"<<; }
ganz rechts wird hier noch was erwartet, was in den Stream geschrieben wird. Entweder entfernst du das <<, oder du packst das std::endl direkt hier hin.
Generell sparst du mit geschweiften Klammern. Zwar beziehen sich FOR und IF etc. immer auf die nächste Zeile, wenn es keine klammern gibt, aber du solltest der Übersicht halber IMMER Klammern benutzen, und auch nur einen Befehl pro Zeile schreiben, sonst wird es unübersichtlich. So finde ich
for(int j=2;(j*j)<i ;i++) if (i%j==0) zw_summe += j+i/j;
schon ziemlich hart.
Wenn du die Bugs ausgemerzt hast, kompiliert dein Code dann?
Übrigens sind die Compilermeldungen auf den ersten Blick kryptisch, häufig sagen sie dir aber auch, welche Fehler, oder zumindest, wo Fehler da sind. Du solltest also auch mal da rein gucken, damit du etwas übung darin bekommst, die Meldungen zu verstehen.
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 18:27 Fr 29.10.2010 | Autor: | felixf |
Moin,
drei kleine Anmerkungen ;)
> for(int j=2;(j*j)<i ;i++) if (i%j==0) zw_summe += j+i/j;
>
> Es ist sicher gut gemeint, zu jedem gefundenen Divisor
> gleich den Quotienten mit zu behandeln. aber da die
> For-Schleife den gesamten Zahlenbereich möglicher
> Divisoren durchläuft, würden die Quotienten auch als
> Divisoren gefunden werden, und wären dann doppelt in der
> Summe drin. Also immer nur den Divisor addieren!
Das stimmt nicht ganz: er durchlaeuft ja nur alles bis [mm] $\sqrt{i}$. [/mm] Damit wird jeder Divisor nur einmal addiert und nicht doppelt.
Allerdings funktioniert das ganze so nicht, wenn $i$ ein Quadrat ist. Das muss man noch extra testen zum Schluss und dann [mm] $\sqrt{i}$ [/mm] nur genau einmal addieren.
> (j*j) läßt sich besser als pow(i,2) schreiben (ggf mit
> include math), aber das paßt schon so.
Ich wuerde stark davon abraten, pow(j, 2) zu schreiben.
Erstens: j*j wird i.A. schnelleren Code erzeugen;
(Ausnahme: pow ist inline, akzeptiert nur Ganzzahlen als Argumente und der Optimierer spezialisiert den Code fuer diesen Fall und streicht ihn entsprechend zusammen. Was doch etwas unwahrscheinlich ist, gerade wegen dem zweiten Punkt)
Zweitens: pow akzeptiert doubles und liefert einen double zurueck, obwohl hier mit ints gearbeitet wird.
> Generell sparst du mit geschweiften Klammern. Zwar beziehen
> sich FOR und IF etc. immer auf die nächste Zeile, wenn es
> keine klammern gibt, aber du solltest der Übersicht halber
> IMMER Klammern benutzen, und auch nur einen Befehl pro
> Zeile schreiben, sonst wird es unübersichtlich. So finde
> ich
> for(int j=2;(j*j)<i ;i++) if (i%j==0) zw_summe += j+i/j;
> schon ziemlich hart.
Ich finde es ohne Klammern schon ok, allerdings wuerde ich es auf drei Zeilen (mit Einrueckungen) verteilen.
LG Felix
|
|
|
|
|
Hallo Even_Horizon
Und danke für deine Tipps.
Ich habe nun mein Programm umgeschrieben und es sieht nun wie folgt aus:
#include <iostream>
int main ()
{
//input
int n=0;
int zw_summe=1;
std::cout<<"Gib alle vollkommenen Zahlen bis n=? aus";
std::cin>>n;
//Bestimmen der Variablen und Eingabe der Schleife
for(int i=n; i>1; i--) // da 1 keine vollkommene Zahl ist beginne ich erst bei i>1
{
for(int j=2;(j*j)<i ;j++)
if (i%j==0)
zw_summe += i/j;
//Output
if(zw_summe==i) std::cout<< i << "sind vollkommene Zahlen!"<<endl;
}
return 0;
}
Ich bin nicht sicher ob ich alle deine Tipps korrekt umgesetzt habe. Auf kann ich das Programm nun compilen, aber wenn ich es in der Konsole testen will, gibt es mir keinen Wert aus.....
Kannst du mir sagen ob das was ich nun programmiert habe, die Anzahl der perfekten Zahlen von 1 bis 50 000 ausgeben sollte wenn ich als Eingabe in der Konsole 50000 eingebe?
Oder muss ich noch etwas verändern? Ich wäre sehr froh, wenn du mir die Änderungen in meinem Programm anzeichnen könntest, ich bin wirklich mit jeder kleinigkeit schon überfragt.
Vielen Dank
|
|
|
|
|
Status: |
(Antwort) fertig | Datum: | 21:20 Fr 29.10.2010 | Autor: | felixf |
Moin!
> Ich habe nun mein Programm umgeschrieben und es sieht nun
> wie folgt aus:
>
>
> #include <iostream>
>
> int main ()
> {
> //input
> int n=0;
> int zw_summe=1;
> std::cout<<"Gib alle vollkommenen Zahlen bis n=? aus";
> std::cin>>n;
>
> //Bestimmen der Variablen und Eingabe der Schleife
> for(int i=n; i>1; i--) // da 1 keine vollkommene Zahl
> ist beginne ich erst bei i>1
> {
> for(int j=2;(j*j)<i ;j++)
> if (i%j==0)
> zw_summe += i/j;
>
> //Output
> if(zw_summe==i) std::cout<< i << "sind vollkommene
> Zahlen!"<<endl;
> }
> return 0;
> }
>
> Ich bin nicht sicher ob ich alle deine Tipps korrekt
> umgesetzt habe. Auf kann ich das Programm nun compilen,
> aber wenn ich es in der Konsole testen will, gibt es mir
> keinen Wert aus.....
Kein Wunder. Du hast zwei Sachen nicht beachtet:
(1) du musst zw_summe zuruecksetzen;
(2) wenn i ein Quadrat ist, hat zw_summe nach der Schleife den falschen Wert.
Das stand auch schon alles im Thread...
(Wobei (2) nicht so wichtig ist, da perfekte Zahlen quadratfrei sind; allerdings musst du noch aufpassen, dass du nicht zufaellig eine Quadratfrei findest, die gleich der Summe aller echten Teiler ausser ihrer Quadratwurzel ist.)
LG Felix
|
|
|
|
|
Hallo
Vielen Dank für deine Antwort
>
>> >
> >
> > #include <iostream>
> >
> > int main ()
> > {
> > //input
> > int n=0;
> > int zw_summe=1;
> > std::cout<<"Gib alle vollkommenen Zahlen bis n=?
> aus";
> > std::cin>>n;
> >
> > //Bestimmen der Variablen und Eingabe der Schleife
> > for(int i=n; i>1; i--) // da 1 keine vollkommene Zahl
> > ist beginne ich erst bei i>1
> > {
> > for(int j=2;(j*j)<i ;j++)
> > if (i%j==0)
> > zw_summe += i/j;
> >
> > //Output
> > if(zw_summe==i) std::cout<< i << "sind
> vollkommene
> > Zahlen!"<<endl;
> > }
> > return 0;
> > }
> >
> > Ich bin nicht sicher ob ich alle deine Tipps korrekt
> > umgesetzt habe. Auf kann ich das Programm nun compilen,
> > aber wenn ich es in der Konsole testen will, gibt es mir
> > keinen Wert aus.....
>
> Kein Wunder. Du hast zwei Sachen nicht beachtet:
>
> (1) du musst zw_summe zuruecksetzen;
>
Nun meine Frage ist einfach wie kann ich denn die Zwischensumme zurücksetzen? Ich komme leider nicht drauf. Entschuldigt bitte wenn ich etwas schwer von begriff bin, aber das ist wirklich alles sehr neu für mich...
> (2) wenn i ein Quadrat ist, hat zw_summe nach der Schleife
> den falschen Wert.
>
> Das stand auch schon alles im Thread...
>
> (Wobei (2) nicht so wichtig ist, da perfekte Zahlen
> quadratfrei sind; allerdings musst du noch aufpassen, dass
> du nicht zufaellig eine Quadratfrei findest, die gleich der
> Summe aller echten Teiler ausser ihrer Quadratwurzel ist.)
Wenn diese Anpassung nicht so wichtig ist, dann werde ich es so lassen....
>
> LG Felix
>
Danke für eure erneute Hilfe
|
|
|
|
|
Status: |
(Antwort) fertig | Datum: | 09:50 Sa 30.10.2010 | Autor: | felixf |
Moin!
> > > #include <iostream>
> > >
> > > int main ()
> > > {
> > > //input
> > > int n=0;
> > > int zw_summe=1;
> > > std::cout<<"Gib alle vollkommenen Zahlen bis n=?
> > aus";
> > > std::cin>>n;
> > >
> > > //Bestimmen der Variablen und Eingabe der Schleife
> > > for(int i=n; i>1; i--) // da 1 keine vollkommene
> Zahl
> > > ist beginne ich erst bei i>1
> > > {
> > > for(int j=2;(j*j)<i ;j++)
> > > if (i%j==0)
> > > zw_summe += i/j;
> > >
> > > //Output
> > > if(zw_summe==i) std::cout<< i << "sind
> > vollkommene
> > > Zahlen!"<<endl;
> > > }
> > > return 0;
> > > }
> > >
> > > Ich bin nicht sicher ob ich alle deine Tipps korrekt
> > > umgesetzt habe. Auf kann ich das Programm nun compilen,
> > > aber wenn ich es in der Konsole testen will, gibt es mir
> > > keinen Wert aus.....
> >
> > Kein Wunder. Du hast zwei Sachen nicht beachtet:
> >
> > (1) du musst zw_summe zuruecksetzen;
> >
> Nun meine Frage ist einfach wie kann ich denn die
> Zwischensumme zurücksetzen? Ich komme leider nicht drauf.
> Entschuldigt bitte wenn ich etwas schwer von begriff bin,
> aber das ist wirklich alles sehr neu für mich...
Du musst der Variablen zw_summe an der richtigen Stelle den Wert 1 zuweisen. An welcher Stelle hat Event_Horizon dir schon gesagt. Und wie man eine Zuweisung macht weisst du doch, du verwendest ja welche im Programm.
> > (2) wenn i ein Quadrat ist, hat zw_summe nach der Schleife
> > den falschen Wert.
> >
> > Das stand auch schon alles im Thread...
> >
> > (Wobei (2) nicht so wichtig ist, da perfekte Zahlen
> > quadratfrei sind; allerdings musst du noch aufpassen, dass
> > du nicht zufaellig eine Quadratfrei findest, die gleich der
> > Summe aller echten Teiler ausser ihrer Quadratwurzel ist.)
>
> Wenn diese Anpassung nicht so wichtig ist, dann werde ich
> es so lassen....
So einfach ist es nicht.
Entweder passt du es an, oder du beweist dass du es nicht anpassen musst.
Es anpassen ist einfacher.
Das "nicht so wichtig" war relativ im Verglekich mit (1) gemeint: wenn du (1) einbaust aber nicht (2), bekommst du eventuell falsche Treffer, aber ansonsten funktioniert es; wenn du dagegen (1) nicht einbaust, bekommst du nix vernuenftiges.
LG Felix
|
|
|
|
|
Hallo
also ich habe nun die Zw_summe vor der 2. For-Schleife auf eins zurückgesetzt. Ich hoffe jedenfalls, dass ich dies an der richtigen Stelle gemacht habe...
#include <iostream>
int main ()
{
//input
int n=0;
int zw_summe=1;
std::cout<<"Gib alle vollkommenen Zahlen bis n=? aus";
std::cin>>n;
//Bestimmen der Variablen und Eingabe der Schleife
for(int i=n; i>1; i--); // da 1 keine vollkommene Zahl ist beginne ich erst bei i>1
{
zw_summe=1;
for(int j=2;(j*j)<i; j++)
if (i%j==0)
zw_summe +=j+i/j;
//Output
if(zw_summe==i) std::cout<< i << " sind vollkommene Zahlen!"<< [mm] "\n";
[/mm]
}
return 0;
}
Aber nun erhalte ich beim Compilen immer folgende Fehlermeldungen:
perfect.cpp: In function ‘int main()’:
perfect.cpp:19:25: error: name lookup of ‘i’ changed for ISO ‘for’ scoping
perfect.cpp:19:25: note: (if you use ‘-fpermissive’ G++ will accept your code)
make: *** [perfect] Fehler 1
Compilation exited abnormally with code 2 at Sat Oct 30 11:02:51
und ich verstehe nicht was hier mit meinem i nicht in Ordnung ist, liegt unter anderem auch am Englisch???
Zu der Sache mit dem quadrat, leider verstehe ich den Kommentar nicht ganz, und ich komme auch nicht drauf, was ich machen soll, damit es kein Quadrat gibt....
Es tut mir leid das ich so schwer von Begriff bin, aber ich habe wirklich keine Ahnung wie ich das umsetzen soll...
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 11:48 Sa 30.10.2010 | Autor: | Disap |
Hallo.
> also ich habe nun die Zw_summe vor der 2. For-Schleife auf
> eins zurückgesetzt. Ich hoffe jedenfalls, dass ich dies an
> der richtigen Stelle gemacht habe...
>
> #include <iostream>
>
> int main ()
> {
> //input
> int n=0;
> int zw_summe=1;
> std::cout<<"Gib alle vollkommenen Zahlen bis n=? aus";
> std::cin>>n;
>
> //Bestimmen der Variablen und Eingabe der Schleife
> for(int i=n; i>1; i--); // da 1 keine vollkommene Zahl
> ist beginne ich erst bei i>1
Hinter der Forschleife ein Semikolon? Ich glaube, das gehört da nicht hin?
> {
> zw_summe=1;
> for(int j=2;(j*j)
hier gehen 2 Klammern auf, aber nur eine zu? Außerdem gilt in dieser Forschleife nur die nächste Zeile(?)
<i; j++)=""></i;>
> if (i%j==0)
> zw_summe +=j+i/j;
>
> //Output
> if(zw_summe==i) std::cout<< i << " sind vollkommene
> Zahlen!"<< <img class="latex" _cke_realelement="true" alt="$" ;$="" src="http://teximg.matheraum.de/render?d=108&s=$" [mm] \n="" [/mm] ;="">
> }
> return 0;
> }
>
> Aber nun erhalte ich beim Compilen immer folgende
> Fehlermeldungen:
>
> perfect.cpp: In function ‘int main()’:
> perfect.cpp:19:25: error: name lookup of ‘i’ changed
> for ISO ‘for’ scoping
> perfect.cpp:19:25: note: (if you use ‘-fpermissive’
> G++ will accept your code)
> make: *** [perfect] Fehler 1
>
> Compilation exited abnormally with code 2 at Sat Oct 30
> 11:02:51
>
> und ich verstehe nicht was hier mit meinem i nicht in
> Ordnung ist, liegt unter anderem auch am Englisch???
>
> Zu der Sache mit dem quadrat, leider verstehe ich den
> Kommentar nicht ganz, und ich komme auch nicht drauf, was
> ich machen soll, damit es kein Quadrat gibt....
>
> Es tut mir leid das ich so schwer von Begriff bin, aber ich
> habe wirklich keine Ahnung wie ich das umsetzen soll...
Deine geschweifte-Klammersetzung finde ich komisch. Gehen die hier im Forum irgendwie verloren?
Und was ist bei dir Zeile 19 bis 25?
Kannst du nicht < code> und < /code> ohne leerzeichen setzen, damit dein Quellcode besser lesbar/übersichtlicher wird (ich empfinde es zumindest so)
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 02:46 So 31.10.2010 | Autor: | felixf |
Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)
Moin!
> > also ich habe nun die Zw_summe vor der 2. For-Schleife auf
> > eins zurückgesetzt. Ich hoffe jedenfalls, dass ich dies an
> > der richtigen Stelle gemacht habe...
> >
> > #include <iostream>
> >
> > int main ()
> > {
> > //input
> > int n=0;
> > int zw_summe=1;
> > std::cout<<"Gib alle vollkommenen Zahlen bis n=?
> aus";
> > std::cin>>n;
> >
> > //Bestimmen der Variablen und Eingabe der Schleife
> > for(int i=n; i>1; i--); // da 1 keine vollkommene
> Zahl
> > ist beginne ich erst bei i>1
>
> Hinter der Forschleife ein Semikolon? Ich glaube, das
> gehört da nicht hin?
Exakt. Das ist das Problem.
> Deine geschweifte-Klammersetzung finde ich komisch. Gehen
> die hier im Forum irgendwie verloren?
Nun, wenn man sich beharrlich weigert, seinen Code als Code zu deklarieren, geht das natuerlich schief, da das Forum versucht die geschweiften Klammern als Formeln aufzufassen.
> Kannst du nicht < code> und < /code> ohne leerzeichen
> setzen, damit dein Quellcode besser lesbar/übersichtlicher
> wird
Besser: [code]...[/code]
> (ich empfinde es zumindest so)
Nicht nur du :)
LG Felix
|
|
|
|
|
Status: |
(Antwort) fertig | Datum: | 02:50 So 31.10.2010 | Autor: | felixf |
Moin!
> also ich habe nun die Zw_summe vor der 2. For-Schleife auf
> eins zurückgesetzt. Ich hoffe jedenfalls, dass ich dies an
> der richtigen Stelle gemacht habe...
Ja, hast du. Dafuer hast du es geschafft ein Semikolon so einzufuegen, dass alles nicht mehr funktioniert.
> Aber nun erhalte ich beim Compilen immer folgende
> Fehlermeldungen:
>
> perfect.cpp: In function ‘int main()’:
> perfect.cpp:19:25: error: name lookup of ‘i’ changed
> for ISO ‘for’ scoping
> perfect.cpp:19:25: note: (if you use ‘-fpermissive’
> G++ will accept your code)
> make: *** [perfect] Fehler 1
>
> Compilation exited abnormally with code 2 at Sat Oct 30
> 11:02:51
>
> und ich verstehe nicht was hier mit meinem i nicht in
> Ordnung ist, liegt unter anderem auch am Englisch???
Die Fehlermeldung richtet sich hauptsaechlich an Leute, die vor-Standard-C++ kennen. Manche alte Compiler "kennen" in for-Schleifen deklarierte Variablen bis zum Ende der Funktion, laut Standard-C++ sind die Variablen nur in der for-Schleife selber gueltig.
Die Meldung tritt hier auf, da du direkt nach der for-Schleife ein Semikolon eingefuegt hast. Sprich, die Schleife fuert $n - 1$ mal nichts aus.
> Zu der Sache mit dem quadrat, leider verstehe ich den
> Kommentar nicht ganz, und ich komme auch nicht drauf, was
> ich machen soll, damit es kein Quadrat gibt....
Berechne mal die Teilersummen von 9 und 10 mit deiner Methode, und vergleiche sie mit der richtigen Teilersumme. Faellt dir was auf?
Wenn nicht, rechne es hier vor.
Wenn du es hinbekommst, ueberlege dir, wie du deine Methode korrigieren musst, damit sie das richtige Ergebnis liefert.
LG Felix
|
|
|
|
|
Hallo
Es hat endlich geklappt. Vielen Dank für eure Hilfe.
|
|
|
|