# Rekursive Methode - Ziffern in Zahl



## chrisööö (18. Nov 2010)

Hallo,
ich bräuchte bei folgender Aufgabenstellung Hilfe

Aufgabe:
Methode realisieren, die für eine Zahl (1. Parameter) und eine Ziffer (2. Parameter) genau dann true liefert, wenn die Ziffer in der Dezimaldarstellung der Zahl vorkommt. Sie dürfen davon ausgehen, dass bei Anwendung der Methode beide Parameter größer oder gleich 0 sind und der zweite Parameter stets kleiner oder gleich 9 ist. 

Beispiel 4711 Parameter 1 und 7 Parameter 2

Nun soll ich durch Rekursion eine Methode schreiben die dies berechnet. Hab auch schon einen Code jedoch ist mein Problem immer das folgende, das ich nicht weiss wie ich jede Stelle einzeln überprüft bekomme. 


```
public static boolean enthaelt(long zahl, int ziffer) {
            return (zahl <= 9)
                   ? zahl == ziffer
                   : enthaelt((zahl % 10), (ziffer));
    }
```

Hier habe ich am Ende immer nur die letzte Stelle der grossen Zahl zur Überprüfung und alle anderen werden übergangen. Kann mir Jemand einen Tip geben?
Danke


----------



## Andi_CH (18. Nov 2010)

Vermutlich gibt es X Wege.

Meine erste Idee ist, beides in einen String zu konvertieren

also "4711" und "7" und dann mit contains überprüfen ob "4711" "7" enthält ...


übrigens liefert deine Funktion true, wenn zahl <= 9 ist, und das  ist ganz sicher nicht die Meinung
ausserdem liefert sie immer false, wenn zahl > 9 ist - also auch das ist falsch ....


----------



## SlaterB (18. Nov 2010)

vergiss vorerst die Rekursion,
versuche zunächst nur die letzte Ziffer zu prüfen
bzw. als nächsten die vorletze,
schreibe ein Programm das genau die vorletzte und letzte prüft,

% 10 ist schon ziemlich gut, / 10 auch noch,
was kommt da bei 4711 raus, was ist 4711 % 10 und was ist 4711 / 10, inwiefern kann dir das helfen?


----------



## chrisööö (18. Nov 2010)

Also 4711 % 10 berechnet mir die alleinige letzte Stelle dank des Restwertoperators.
4711 / 10 verkürzt mir die Zahl um eine Stelle da bei Int die Nachkommastelle abgeschnitten wird. Allerdings kann ich ja keine 3 Stellige Zahl auf Inhalt einer Einstelligen prüfen. Somit hatte ich schon das Problem das er nur die vorderste Stelle überprüft hat


----------



## Andi_CH (18. Nov 2010)

Bis zur Rekursion kommt er gar nicht - siehe 

```
return (zahl <= 9)
```


----------



## chrisööö (18. Nov 2010)

Andi_CH hat gesagt.:


> Vermutlich gibt es X Wege.
> 
> Meine erste Idee ist, beides in einen String zu konvertieren
> 
> ...



Falsch: Sie prüft ob die Zahl <= 9 ist und wenn ja, springt Sie in den Ja Zweig und wertet aus, ob die Zahl == der Ziffer ist. Dank boolean gibt es dann die Ausgabe true oder false. Wenn die Zahl mehrere Stellen hat spring Sie in den Nein Zweig


----------



## Andi_CH (18. Nov 2010)

chrisööö hat gesagt.:


> Also 4711 % 10 berechnet mir die alleinige letzte Stelle dank des Restwertoperators.
> 4711 / 10 verkürzt mir die Zahl um eine Stelle da bei Int die Nachkommastelle abgeschnitten wird. Allerdings kann ich ja keine 3 Stellige Zahl auf Inhalt einer Einstelligen prüfen. Somit hatte ich schon das Problem das er nur die vorderste Stelle überprüft hat



Wenn du es schon kompliziert machen willst (das mit String ist viel einfacher) musst du:

überprüfen ob der Restwert der Ziffer entspricht
falls ja -> return true
falls es keine weiteren Ziffern mehr gibt (zahl < 10) return false
else zahl um eine Stelle verkürzen

und das Ganze in einem geschickten Loop ;-)


----------



## SlaterB (18. Nov 2010)

chrisööö hat gesagt.:


> Also 4711 % 10 berechnet mir die alleinige letzte Stelle dank des Restwertoperators.
> 4711 / 10 verkürzt mir die Zahl um eine Stelle da bei Int die Nachkommastelle abgeschnitten wird. Allerdings kann ich ja keine 3 Stellige Zahl auf Inhalt einer Einstelligen prüfen. Somit hatte ich schon das Problem das er nur die vorderste Stelle überprüft hat


nur die hinterste statt die vorderste, 
aber da hilft eben die Rekursion, mit der verkürzten Zahl 471 genau dasselbe nochmal machen,
wieder die vermeintlich letze Ziffer abtrennen (nun die vorletzte der Originalzahl),
dann wieder /10 und mit 47 weitermachen,
immer weiter per Rekursion bis ganze Zahl durch


----------



## Andi_CH (18. Nov 2010)

chrisööö hat gesagt.:


> Falsch: Sie prüft ob die Zahl <= 9 ist und wenn ja, springt Sie in den Ja Zweig und wertet aus, ob die Zahl == der Ziffer ist. Dank boolean gibt es dann die Ausgabe true oder false. Wenn die Zahl mehrere Stellen hat spring Sie in den Nein Zweig



Könntest du das bitte in einer lesbaren if - else Form schreiben? Ich verstehe die verkrü.... C-Notation nicht - (die gehört IMHO aus dem Sprachumfang gestrichen)

Aber die Lösung habe ich ja eben beschrieben - ohne Rekursion in einem Loop


----------



## chrisööö (18. Nov 2010)

Andi_CH hat gesagt.:


> Wenn du es schon kompliziert machen willst (das mit String ist viel einfacher) musst du:
> 
> überprüfen ob der Restwert der Ziffer entspricht
> falls ja -> return true
> ...



Nun erstmal würde ich es mir gerne leichter machen, allerdings ist die Vorgabe eine Rekursion zur Lösung.
Dazu kommt noch das Sie mit den einfachsten Mitteln wie ?: und % oder / usw. gerechnet werden soll. Vor dem Rekursiven Aufruf dürfte auch alles richtig sein, allerdings finde ich keine Formel, die mir beim Rekursiven Aufruf die nächste Stelle einzeln usw. überprüft bis die Zahl komplett auf Inhalt der Ziffer überprüft wurde und genau das ist mein Problem.


----------



## Michael... (18. Nov 2010)

chrisööö hat gesagt.:


> Allerdings kann ich ja keine 3 Stellige Zahl auf Inhalt einer Einstelligen prüfen. Somit hatte ich schon das Problem das er nur die vorderste Stelle überprüft hat


Darum geht's ja bei der Rekursion. In der Methode holst Du per Modulo die letzte Ziffer und überprüfst auf Gleichheit zum zweiten Parameter. Falls nein, ruft die Methode sich selbst auf und übergibt die "verkürzte" erste Zahl als Parameter, usw.


----------



## Mofi (18. Nov 2010)

chrisööö hat gesagt.:


> Nun erstmal würde ich es mir gerne leichter machen, allerdings ist die Vorgabe eine Rekursion zur Lösung.
> Dazu kommt noch das Sie mit den einfachsten Mitteln wie ?: und % oder / usw. gerechnet werden soll. Vor dem Rekursiven Aufruf dürfte auch alles richtig sein, allerdings finde ich keine Formel, die mir beim Rekursiven Aufruf die nächste Stelle einzeln usw. überprüft bis die Zahl komplett auf Inhalt der Ziffer überprüft wurde und genau das ist mein Problem.



Aber ein if/else darf schon noch drin sein? Weil einfacher ist der ?: nicht wirklich in meinen Augen.
Ansonsten fehlt irgendwie einfach die Überprüfung des "Rests" des Modulo mit der Ziffer (find ich zumindestes), weil was bringt es dir es nur "abzutrennen"?


----------



## chrisööö (18. Nov 2010)

Michael... hat gesagt.:


> Darum geht's ja bei der Rekursion. In der Methode holst Du per Modulo die letzte Ziffer und überprüfst auf Gleichheit zum zweiten Parameter. Falls nein, ruft die Methode sich selbst auf und übergibt die "verkürzte" erste Zahl als Parameter, usw.



Das ist klar. Allerdings übergibt er mir ja nun nur die 1Stellige Zahl die ich per % ausgewertet habe. Somit spring er nach Aufruf der Rekursion in den Ja-Zweig und gibt mir false aus, da die 1 nicht == der 7 ist 

Brauche ich hier nochmal eine Unterabfrage oder so etwas?


----------



## chrisööö (18. Nov 2010)

Mofi hat gesagt.:


> Aber ein if/else darf schon noch drin sein? Weil einfacher ist der ?: nicht wirklich in meinen Augen.
> Ansonsten fehlt irgendwie einfach die Überprüfung des "Rests" des Modulo mit der Ziffer (find ich zumindestes), weil was bringt es dir es nur "abzutrennen"?



Nein, darf leider nicht.


----------



## Andi_CH (18. Nov 2010)

Also wenn du das was ich in Pseudocode umschreiben haben umsetzt sieht es doch etwa so aus - oder nicht?

```
private static boolean pruefe (int pZahl, int pZiffer) {
	if (pZahl%10==pZiffer)
		return true;
	if (pZahl<10)
		return false;
	return pruefe(pZahl/10, pZiffer);
}
```


----------



## Andi_CH (18. Nov 2010)

Ohne if geht es nicht - wie willst du denn die Rekursion abbrechen?


----------



## Michael... (18. Nov 2010)

chrisööö hat gesagt.:


> Das ist klar. Allerdings übergibt er mir ja nun nur die 1Stellige Zahl die ich per % ausgewertet habe. Somit spring er nach Aufruf der Rekursion in den Ja-Zweig und gibt mir false aus, da die 1 nicht == der 7 ist
> 
> Brauche ich hier nochmal eine Unterabfrage oder so etwas?


Habe ja auch geschrieben, dass die Zahl und nicht die letzte Ziffer an die Methode übergeben wird.
Wenn Du nur den Divisionsrest an die Methode übergibst, wie willst Du da etwas rekursiv aufrufen.


----------



## Andi_CH (18. Nov 2010)

chrisööö hat gesagt.:


> Dazu kommt noch das Sie mit den einfachsten Mitteln wie ?: und % oder / usw. gerechnet werden soll.


?: als einfach zu bezeichnen übersteigt meine Vorstellungskraft :bahnhof: - ausserdem ist das nichts anderes als die unleserliche Variante von if ....

Irgendwann hat man mal Hochsprachen eingeführt um vom Assembler weg zu kommen und dann sowas ...


----------



## chrisööö (18. Nov 2010)

Andi_CH hat gesagt.:


> Ohne if geht es nicht - wie willst du denn die Rekursion abbrechen?



Sie bricht dann ab, sobald die Zahl <= 9 ist, denn dann wertet er ja aus, ob die Zahl == Ziffer ist. Wenn Ja, true wenn Nein, false.


```
public static boolean enthaelt(long zahl, int ziffer) {
            return (zahl <= 9)
                   ? zahl == ziffer
                   : enthaelt((zahl / 10), (ziffer));
```

Hier geht er bis zur ersten Stelle, der 4. Wenn ich auf Inhalt von 4 prüfe gibt er mir somit true aus. Alle Zahlen zwischen der Zahl 4711 (also ausser der 4) übergeht er dann aber.


----------



## Andi_CH (18. Nov 2010)

Entscheidung 1: Ist der Zahlenrest gleich der Ziffer? -> Abbrechen und true sagen

Entscheidung 2: Ist die Zahl < 10 -> Weitermachen oder nicht, wenn nicht false sagen

Um diese zwei kommst du nicht rum! Das ist ein Naturgesetz. Wie auch immer du die formulierst - es ist und bleiben Entscheidungen


----------



## Michael... (18. Nov 2010)

Deine Überprüfung ist auch falsch, zum einen müsst Du Überprüfen ob der Divisionsrest der Zahl entspricht und ob Du bei der letzten Ziffer angelangt bist.


----------



## chrisööö (18. Nov 2010)

Michael... hat gesagt.:


> Habe ja auch geschrieben, dass die Zahl und nicht die letzte Ziffer an die Methode übergeben wird.
> Wenn Du nur den Divisionsrest an die Methode übergibst, wie willst Du da etwas rekursiv aufrufen.



Hey supi ich habs endlich  Danke

Habe die Formel noch mit einer Unterabfrage umgestellt:


```
public static boolean enthaelt(long zahl, int ziffer) {
            return (zahl <= 9)
                   ? zahl == ziffer
                   : ((zahl % 10) == ziffer)
                   ? true
                   : enthaelt((zahl / 10), (ziffer));
```
:applaus:


----------



## Andi_CH (18. Nov 2010)

Klar du hast eine Entscheidung eingespart in dem du einfach den Zahlenrest nie berücksichtigst - mag genial aussehen, ist aber genial falsch :-(

siehe oben -> es braucht zwingend 2 Entscheidungen - mit weniger geht es nicht.

Und BITTE schreib die in if-Form - derjenige der behauptet es sei besser in ?: Form soll sich BITTE mit mir persönlich unterhalten. Der muss mir nämlich erklären warum das besser sein soll!
(Glaub mir, die Möglichkeit, dass ich mindestens so viel Erfahrung habe wie der, ist gegeben)


----------



## Andi_CH (18. Nov 2010)

jetzt noch die lesbare Form ....


----------



## chrisööö (18. Nov 2010)

Andi_CH hat gesagt.:


> Klar du hast eine Entscheidung eingespart in dem du einfach den Zahlenrest nie berücksichtigst - mag genial aussehen, ist aber genial falsch :-(
> 
> siehe oben -> es braucht zwingend 2 Entscheidungen - mit weniger geht es nicht.
> 
> ...



Kannst dich gerne mit meinem Proffessor darüber streiten. Im prinzip ist mir das völlig Wurst, da ich Anfänger bin und er die Aufgabe nunmal so gestellt hat und somit auch so gelöst haben will  Da ändere auch ich nichts dran. Mir gehts hier um eine Lösung und nicht um eine Grundsatzdiskussion. Die Lösung habe ich ja nun.


----------



## Mofi (18. Nov 2010)

chrisööö hat gesagt.:


> Kannst dich gerne mit meinem Proffessor darüber streiten. Im prinzip ist mir das völlig Wurst, da ich Anfänger bin und er die Aufgabe nunmal so gestellt hat und somit auch so gelöst haben will  Da ändere auch ich nichts dran. Mir gehts hier um eine Lösung und nicht um eine Grundsatzdiskussion. Die Lösung habe ich ja nun.



Den Professor würde ich auch gerne mal kennen lernen. Ich mein das als "einfach" zuverkaufen ist schon...Es ist definitv schlecht lesbar und ich kenne viele die mit diesem Ausdruck einfach überfordert wären, obwohl sie ja "toll" programmieren können (aus ihrer eigenen Sicht, ich beurteile es nicht, da ich nur bedingt den Code kenne).

Findest du denn den Code so eifnach zu verstehen? Ich mein ich musste den auch dreimal lesen um da hinter zusteigen...Ein if/else Konstrukt ist meines Erachtens auf den ersten Blick verständlicher.


----------



## ARadauer (18. Nov 2010)

> - derjenige der behauptet es sei besser in ?: Form soll sich BITTE mit mir persönlich unterhalten


weils cooler ist


----------



## chrisööö (18. Nov 2010)

Mofi hat gesagt.:


> Den Professor würde ich auch gerne mal kennen lernen. Ich mein das als "einfach" zuverkaufen ist schon...Es ist definitv schlecht lesbar und ich kenne viele die mit diesem Ausdruck einfach überfordert wären, obwohl sie ja "toll" programmieren können (aus ihrer eigenen Sicht, ich beurteile es nicht, da ich nur bedingt den Code kenne).
> 
> Findest du denn den Code so eifnach zu verstehen? Ich mein ich musste den auch dreimal lesen um da hinter zusteigen...Ein if/else Konstrukt ist meines Erachtens auf den ersten Blick verständlicher.



Bis dato kannte ich auch nur if / else und fand es logisch. Allerdings soll der ?: Operator bei Berechnungen um einiges schneller sein.  Aber prinzipiell ist es mir egal, solange ich es verstehe und damit Aufgaben lösen kann.


----------



## bygones (18. Nov 2010)

chrisööö hat gesagt.:


> Allerdings soll der ?: Operator bei Berechnungen um einiges schneller sein.


jo bei drölfmillionen berechnungen wirds ungefähr 0,0000000000000001 ms schneller.... go for it

edit meint sie sei verwirrt weil ?: als elvis operator ne andere semantik hat wie hier diskutiert wird....


----------



## bone2 (18. Nov 2010)

[ JAVA] [/ JAVA]
wären schon ein anfang für die lesbarkeit


```
public static boolean enthaelt(long zahl, int ziffer) {
        if (zahl <= 0) {
            return false;
        }
        else {
            if ((zahl % 10) == ziffer) {
                return true;          
            }
            else {
                return enthaelt(zahl / 10, ziffer);                
            }
        }
    }
```


----------



## Landei (18. Nov 2010)

```
public static boolean enthaelt(long zahl, int ziffer) {
    return (zahl == 0) ? false 
           : zahl % 10 == ziffer || enthaelt(zahl / 10, ziffer);
}
```


----------



## Andi_CH (18. Nov 2010)

bone2 hat gesagt.:


> [ JAVA] [/ JAVA]
> wären schon ein anfang für die lesbarkeit
> 
> 
> ...



Spar dir die else nach einem return ;-) - vgl mein Code von früher 


```
private static boolean pruefe (int pZahl, int pZiffer) {
    if (pZahl%10==pZiffer)
        return true;
    if (pZahl<10)
        return false; // kann nur noch false sein!
    return pruefe(pZahl/10, pZiffer);
}
```


----------



## bone2 (18. Nov 2010)

stimtm natürlich^^ hatte eigentlich nur ein return und ne boolean variable drin.


----------



## Andi_CH (18. Nov 2010)

bone2 hat gesagt.:


> stimtm natürlich^^ hatte eigentlich nur ein return und ne boolean variable drin.



Das gefällt mir bekanntlich auch viel besser, aber da hier ja Kompaktheit gefragt war ....
(Vermutlich war der Gedanke, dass dadurch das Programm schneller wird :lol: )


----------

