Rekursion < C/C++ < Programmiersprachen < Praxis < Informatik < Vorhilfe
|
Status: |
(Frage) beantwortet | Datum: | 21:14 So 20.12.2009 | Autor: | az118 |
Aufgabe | Eine natürliche Zahl heisst Armstrong-Zahl, wenn die Summe ihrer mit der Länge der
Zahl potenzierten Ziffern gleich der Zahl selbst ist. Beispielsweise ist 153 = [mm] 1^{3} [/mm] + [mm] 5^{3} [/mm] + [mm] 3^{3}
[/mm]
eine Armstrong-Zahl.
a) Schreiben Sie eine rekursive Funktion Laenge, die für eine beliebige natürliche Zahl
die Anzahl ihrer Dezimalziffern als Funktionswert liefert.
b) Schreiben Sie eine Boolesche Funktion Armstrong, die eine beliebige natürliche
Zahl daraufhin testet, ob sie eine Armstrong-Zahl ist. Rufen Sie dazu die Funktion
Laenge auf.
c) Schreiben Sie ein Hauptprogramm, das alle Armstrong-Zahlen von 1 bis 10000
bestimmt. Rufen Sie dazu die Funktion Armstrong auf.
|
Hallo,habe noch eine Aufgabe mit der ich nicht klar komme. Wenn mir jemand helfen könnte,wäre super?
|
|
|
|
Hallo,
es steht doch fast alles da.
Du brauchst eine Funktion "Laenge", die die Zahl der Ziffern feststellt.
Du wirst eine Funktion "Stelle" benötigen, die Dir die k-te Stelle der Zahl (egal ob von vorn oder hinten, Hauptsache eindeutig) liefert.
Die Funktion "Armstrong" ist dann leicht zu definieren.
Abschließend baust Du alles in ein Programm ein, das auf der Hauptebene den geforderten Zahlenbereich durchläuft, einmal die Funktion "Laenge" aufruft (Rückgabe: L), dann die Funktion "Armstrong", welche wiederum L-mal die Funktion "Stelle" aufrufen wird.
Gibt "Armstrong" ein "wahr" zurück, solltest Du die gefundene Zahl in einem Array abspeichern oder einfach direkt ausgeben.
Du wirst folgende finden:
153
370
371
407
1634
8208
9474
Eine Liste für alle Zahlsysteme bis zur Basis 16 findest du hier.
Über die obige Liste hinaus wirst Du übrigens auch die trivialen Lösungen 1 bis 9 finden (jede einstellige Zahl erfüllt ja das Kriterium).
Es gibt insgesamt nur 88 Armstrongzahlen im Dezimalsystem.
Viel Erfolg!
rev
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 16:49 Mo 21.12.2009 | Autor: | az118 |
Ok, aber ich weiß nicht,wie ich die Zahl der Ziffern ermitteln kann bei C ?
|
|
|
|
|
Hallo,
das hängt doch nicht von der Programmiersprache ab.
Wenn gilt [mm] b^s \le z
Logarithmiert ergibt sich also:
[mm] s\le \log_b{z}
Wenn Du über die Gaußklammerfunktion verfügst (in Excel z.B. GANZZAHL(z)), dann ist das doch nur noch ein Rechenschritt, zumal Du ja dezimale Armstrongzahlen suchst und daher b=10 setzen kannst und musst.
Du kannst es auch rekursiv lösen, aber das scheint mir hier nicht nötig.
lg
rev
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 17:11 Mo 21.12.2009 | Autor: | az118 |
Ok, habe jetzt nochmal was versucht.Also wenn ich verschiedene Testzahlen eingebe,gibt mir das Programm die richtige Anzahl der Ziffern aus.stimmt das so?
#include <stdio.h>
int laenge(int k){
int stelle=0;
do ++stelle;
while(k/=10);
return stelle;
}
int main(){
int zahl=137;
printf("Die Zahl besitzt %i Stellen",laenge(zahl));
[mm] while(getchar()!='\r');
[/mm]
}
|
|
|
|
|
Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)
> Ok, habe jetzt nochmal was versucht.Also wenn ich
> verschiedene Testzahlen eingebe,gibt mir das Programm die
> richtige Anzahl der Ziffern aus.stimmt das so?
>
> #include <stdio.h>
>
> int laenge(int k){
> int stelle=0;
>
> do ++stelle;
> while(k/=10);
>
> return stelle;
> }
>
>
> int main(){
> int zahl=137;
>
> printf("Die Zahl besitzt %i Stellen",laenge(zahl));
>
> [mm] while(getchar()!='\r');[/mm]Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)
>
> }
ob ersteres funktioniert oder nicht, die aufgabe verlangt leider eine rekursive lösung für die anzahl der stellen. da musst du dir quasi nochmal gedanken machen
gruß tee
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 18:13 Mo 21.12.2009 | Autor: | az118 |
Also könnte ich jetzt nicht so weiter machen?
Was müsste ich denn ändern?
|
|
|
|
|
> Also könnte ich jetzt nicht so weiter machen?
> Was müsste ich denn ändern?
wenn die erste aufgabe NICHT rekursiv zu lösen wär, wäre
1: | int stellen(k) {
| 2: | return floor(log10(k))+1 ;
| 3: | } |
mit reverends hinweis auf den logarithmus die kürzere variante, jedoch sollst du es ja (warum auch immer) rekursiv lösen (ich bin kein fan davon, probiere aber gerade daran herum)
also in der funktion die du aufrufst, musst du die selbe funktion nochmal aufrufen (rekursion), darauf wird ja explizit bestanden in der aufgabe
gruß tee
|
|
|
|
|
Hallo nochmal.
Sorry, dass die Aufgabe explizit rekursive Gestalt für die Funktion verlangt, hatte ich schon wieder verdrängt. Aber meinetwegen, hier in einem Psedocode
Funktion "Länge"(z,s)
[mm] \quad [/mm] z=floor(z/10)
[mm] \quad [/mm] s=s+1
[mm] \quad [/mm] if z<>0 then s="Länge"(z,s)
[mm] \quad [/mm] else end
Fertig. Die Funktion wird zum ersten Mal aufgerufen mit z als der zu untersuchenden Zahl und s=0. Sie ruft sich solange selbst auf, bis z=0 ist und s die gesuchte Länge.
Die Struktur ist so in jeder Programmiersprache machbar, sofern sie rekursive Funktionen erlaubt. Würde nämlich jedesmal ein Unterprogramm "Länge" aufgerufen, müsste der Abbruch jedes einzelnen Aufrufs sichergestellt werden (return).
Ich hoffe, das ist auch dann verständlich, wenn ich eben nicht in C schreibe.
lg
rev
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 19:02 Mo 21.12.2009 | Autor: | fencheltee |
> Eine natürliche Zahl heisst Armstrong-Zahl, wenn die Summe
> ihrer mit der Länge der
> Zahl potenzierten Ziffern gleich der Zahl selbst ist.
> Beispielsweise ist 153 = [mm]1^{3}[/mm] + [mm]5^{3}[/mm] + [mm]3^{3}[/mm]
> eine Armstrong-Zahl.
>
> a) Schreiben Sie eine rekursive Funktion Laenge, die für
> eine beliebige natürliche Zahl
> die Anzahl ihrer Dezimalziffern als Funktionswert
> liefert.
nach langem grübeln ist mir der sinn der rekursion bezüglich der länge nicht gekommen. an deiner stelle würde ich dann wohl doch einfach ein iteratives verfahren nutzen
dann kannst du dich wenigstens schonmal an die anderen aufgaben begeben
>
> b) Schreiben Sie eine Boolesche Funktion Armstrong, die
> eine beliebige natürliche
> Zahl daraufhin testet, ob sie eine Armstrong-Zahl ist.
> Rufen Sie dazu die Funktion
> Laenge auf.
>
> c) Schreiben Sie ein Hauptprogramm, das alle
> Armstrong-Zahlen von 1 bis 10000
> bestimmt. Rufen Sie dazu die Funktion Armstrong auf.
>
> Hallo,habe noch eine Aufgabe mit der ich nicht klar komme.
> Wenn mir jemand helfen könnte,wäre super?
gruß tee
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 19:11 Mo 21.12.2009 | Autor: | az118 |
Ok,dann lass ich die erste Aufgabe jetzt so und mach mich mal an die anderen.
Nur wie beginne ich mit der zweiten Aufgabe?
|
|
|
|
|
> Ok,dann lass ich die erste Aufgabe jetzt so und mach mich
> mal an die anderen.
> Nur wie beginne ich mit der zweiten Aufgabe?
also als beispiel nehmen wir mal die 153... nun überlege dir, wie du die 1 isoliert kriegst, die 5, und die 3 (stichwort schleife+mod). das dürfte "den schwierigsten" teil ausmachen...
wenn die zahlen am ende isoliert sind, muss jede ziffer mit stellen(zahl) potenziert werden (funktion pow(basis,exponent)) und muss die zahl selber ergeben..
[mm] 1^3+5^3+3^3=153? [/mm] ja, also ist sie eine armstrong zahl
gruß tee
|
|
|
|
|
Nochn Tipp:
am leichtesten ist immer die letzte Ziffer abzutrennen. Im Prinzip fast wie bei der rekursiven Fassung der Längenbestimmung, nur dass Du für die abgetrennte Ziffer noch eine Variable brauchst, die Du zuerst berechnen musst. Dann gleich die Ziffer potenzieren und zu einer Zwischensumme addieren. Letzte Ziffer jetzt endgültig abtrennen. Prüfen, ob die Arbeitsvariable noch <>0 ist. Wieder von vorn.
Klar?
rev
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 19:44 Mo 21.12.2009 | Autor: | az118 |
Noch nicht wirklich?Habe gerade noch mit der Funktion Länge zu kämpfen.Liefert mir immer nen falsches Ergebnis,also muss ich den Fehler erstmal suchen.
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 20:57 Mo 21.12.2009 | Autor: | az118 |
Also ich bekomme hier nix mehr hin.Habe jetzt hin und her probiert.
Wie kann ich denn die einzelnen Ziffern abspeichern um sie zu potenzieren?
|
|
|
|
|
Hallo nochmal,
wenn Du die letzte Ziffer lz von z abschneiden willst, dann ist lz=z-10*floor(z/10). Danach solltest Du aber z auch entsprechend verkürzen, also z:=floor(z/10).
Kommst Du damit weiter?
lg
rev
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 21:36 Mo 21.12.2009 | Autor: | az118 |
und dann lz und z potenzieren mit der anzahl der stellen aus der funktion länge?
|
|
|
|
|
Hallo nochmal,
> und dann lz und z potenzieren mit der anzahl der stellen
> aus der funktion länge?
lz ja, aber wozu z?
Wenn Du die Zahl 339752 untersuchst und sie irgendwann auf 3397 zurechtgestutzt hast, willst Du doch gar nicht wissen, was [mm] 3397^6 [/mm] ist, oder?
lg
rev
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 09:26 Di 22.12.2009 | Autor: | az118 |
Ok also muss ich z solange durch 10 teilen bis z=0 ist?
So richtig weiß ich noch nicht weiter.
|
|
|
|
|
Moin!
Ich glaube, Du bist zuviel aufs Programmieren eingeschossen statt aufs Überlegen. Das bisschen C/C+, das ich mal benutzt habe, habe ich ziemlich vollständig wieder vergessen. Aber darum geht es doch auch erstmal gar nicht.
Du willst die einzelnen Ziffern von z:=339752 haben. Es sei schon bekannt, dass die "Länge" der Zahl s=6 ist, sie also sechsstellig ist. Die Variable as sei zu Beginn as:=0
1. Schritt: Du findest heraus, wie Du lz auf 2 setzen kannst. Funktion stand schon oben.
2. Schritt: Du kürzt z um diese Endziffer. Funktion stand auch schon oben. Dann ist das neue z:33975
3. Schritt: Du tust mit lz, was immer Du mit lz tun musst. Hier also: as:=as+lz^s
4. Schritt: Ist z=0? Wenn nein, dann wieder von vorn:
1. Schritt: lz wird jetzt 5.
2. Schritt: z wird verkürzt. Neues z ist 3397
3. Schritt: as:=as+lz^s
4. Schritt: z=0? Wenn nein, dann wieder von vorn:
1. Schritt: lz wird jetzt 7.
2. Schritt: z wird verkürzt. Neues z ist 339
3. Schritt: as:=as+lz^s
4. Schritt: z=0? Wenn nein, dann wieder von vorn:
1. Schritt: lz wird jetzt 9.
2. Schritt: z wird verkürzt. Neues z ist 33
3. Schritt: as:=as+lz^s
4. Schritt: z=0? Wenn nein, dann wieder von vorn:
1. Schritt: lz wird jetzt 3.
2. Schritt: z wird verkürzt. Neues z ist 3
3. Schritt: as:=as+lz^s
4. Schritt: z=0? Wenn nein, dann wieder von vorn:
1. Schritt: lz wird jetzt 3.
2. Schritt: z wird verkürzt. Neues z ist 0
3. Schritt: as:=as+lz^s
4. Schritt: z=0? Wenn ja, dann weiter:
5. Schritt: as enthält jetzt die gesuchte Zahl. Ein letzter Vergleich: ist das ursprüngliche z (das irgendwo zwischengespeichert worden sein muss, z.B. in zz) gleich der ermittelten Summe, also as=zz? Wenn ja, ausgeben oder abspeichern oder Sekt öffnen oder Computer ausschalten oder was auch immer.
So. Das war ein kompletter Durchlauf für eine sechsstellige Zahl. Alles, was Du aber noch schreiben musst, sind die 5 Schritte, von denen vier immer wieder durchlaufen werden. Eine bedingte Schleife.
Im Beispiel oben ergibt sich as übrigens zu 666237. Dann ist 339752 also keine Armstrongzahl.
Dann mal los.
Good luck,
reverend
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 13:00 Di 22.12.2009 | Autor: | az118 |
Ich habe jetzt erstmal nochmal versucht die funktion "länge" rekursiv zu schreiben,allerdings tritt da ein Fehler auf,von dem ich nicht weiß,was ich nun ändern muss?
#include <stdio.h>
#include <math.h>
int laenge(int z){
double floor;
int s;
z=floor(z/10);
s=s+1;
if (z!=0)
{s=laenge(z);}
return s;
}
int main(){
int zahl=153;
printf(" %i",laenge(zahl));
[mm] while(getchar()!='\r');
[/mm]
}
Der Fehler:"Ausdruck ergibt keine Funktion, die 1 Argumente übernimmt" ??? Fehler tritt in Zeile "z=floor(z/10)" auf???
|
|
|
|
|
Hallo az118,
1: | > #include <stdio.h>
| 2: | > #include <math.h>
| 3: | >
| 4: | > int laenge(int z){
| 5: | > double floor; |
Du deklarierst also eine Variable floor, welche irgendwie die Definition der Funktion floor() aus 'math' "überschreibt". Daher ...
> z = floor(z/10);
... kriegst du hier einen entsprechenden Fehler. Die Lösung ist "double floor;" zu entfernen.
1: | > int s;
| 2: | > [..]
| 3: | > s = s + 1;
| 4: | > [..]
| 5: | > return s; |
Die Variable s hat bei dir am Anfang keinen eindeutigen Anfangswert. Ich muß gestehen, daß ich die Diskussion hier nicht durchgelesen habe. Also ist das wirklich so von dir beabsichtigt?
Viele Grüße
Karl
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 14:31 Di 22.12.2009 | Autor: | az118 |
Ok,habe das floor jetzt weggelassen.Jetzt wird der Fehler auch nicht mehr angezeigt,aber die Ausgabe ist immernoch falsch.Das muss an dem s liegen.Habe s=0 gesetzt anfangs,aber eigentlich wird das s ja hochgezählt soviel wie die zahl ziffern hat oder?aber wie ändere ich die deklaration?
|
|
|
|
|
Hallo az118,
> falsch.Das muss an dem s liegen.Habe s=0 gesetzt
> anfangs,aber eigentlich wird das s ja hochgezählt soviel
> wie die zahl ziffern hat oder?
Zur Bestimmung der Länge einer Zahl kannst du deine Funktion vereinfachen:
1: | #include <stdio.h>
| 2: | #include <math.h>
| 3: |
| 4: | int laenge(int z) {
| 5: | static int onetimecheck = 1;
| 6: |
| 7: | if(onetimecheck == 1) {
| 8: | if (z < 0)
| 9: | return -1;
| 10: | if (z == 0)
| 11: | return 1;
| 12: |
| 13: | onetimecheck = 0;
| 14: | }
| 15: |
| 16: | if (z != 0) {
| 17: | z=floor(z/10);
| 18: | return 1 + laenge(z);
| 19: | } else return 0;
| 20: | }
| 21: |
| 22: | int main() {
| 23: | int zahl; zahl = 153;
| 24: |
| 25: | printf(" %i",laenge(zahl));
| 26: |
| 27: | while(getchar()!='\n');
| 28: | } |
'onetimecheck' dient lediglich dazu die Sachen innerhalb des ersten if-Block nur einmal aufzurufen. Durch static wird die Variable nämlich nur ein einziges Mal initialisiert, da ihr intern auf dem Programm-Heap (und nicht auf dem Stack der Funktion) Speicher zur Verfügung gestellt wird. Hier ein Beispiel zur Funktionsweise der restlichen Funktion: [mm]\operatorname{laenge}(153)=\operatorname{laenge}(15)+1=\operatorname{laenge}(1)+1+1=\operatorname{laenge}(0)+1+1+1=0+1+1+1=3\![/mm]
Gruß V.N.
|
|
|
|
|
Status: |
(Frage) überfällig | Datum: | 15:11 Di 22.12.2009 | Autor: | az118 |
Super danke.
Und wie kann ich die Funktion "länge" in der Funktion "armstrong" nochmal aufrufen?
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 15:20 Do 24.12.2009 | Autor: | matux |
$MATUXTEXT(ueberfaellige_frage)
|
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 13:57 Di 22.12.2009 | Autor: | az118 |
Ok habe versucht die Funktion "armstrong"(aufgabe b) mal zu schreiben,ohne a.
Das Problem ist,dass ich nicht weiß wie und wo ich power(basis,exponent) einfüge,deswegen habe ich es jetzt erstmal per hand lz*lz gesetzt.da ich das programm ohne a versucht habe,musste ich die anzahl der stellen angeben.
haut die programm ohne bezug auf a erstmal soweit hin?
#include <stdio.h>
#include <math.h>
int armstrong(int k){
int as = 0;
int zz=k;
int lz;
double floor (double);
while (k!=0){
lz=k-10*floor(k/10);
k=floor(k/10);
as=as+lz*lz;
}
if (as==zz){
return as;
}
}
int main(){
int zahl=15;
printf("%i",armstrong(zahl));
[mm] while(getchar()!='\r');
[/mm]
}
|
|
|
|
|
Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)
> Ok habe versucht die Funktion "armstrong"(aufgabe b) mal zu
> schreiben,ohne a.
>
> Das Problem ist,dass ich nicht weiß wie und wo ich
> power(basis,exponent) einfüge,deswegen habe ich es jetzt
> erstmal per hand lz*lz gesetzt.da ich das programm ohne a
> versucht habe,musste ich die anzahl der stellen angeben.
> haut die programm ohne bezug auf a erstmal soweit hin?
du hättest doch erstmal die iterative lösung nehmen können. nun sind ja einige rekursive lösungen da, dann kannst du das ja verarbeiten. ohne bezug auf a macht das ganze also nicht viel sinn
>
> #include <stdio.h>
> #include <math.h>
>
> int armstrong(int k){
> int as = 0;
> int zz=k;
> int lz;
> double floor (double);
>
> while (k!=0){
> lz=k-10*floor(k/10);
> k=floor(k/10);
> as=as+lz*lz;
>
> }
> if (as==zz){
> return as;
> }
> }
>
> int main(){
> int zahl=15;
>
> printf("%i",armstrong(zahl));
>
> [mm] while(getchar()!='\r');[/mm]Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)
>
> }
|
|
|
|