Hilfe Rekursion (Haskell) |
nature6
Jungspund
Dabei seit: 16.04.2020
Beiträge: 11
|
|
|
16.04.2020 17:08 |
|
|
NixJava unregistriert
|
|
Zitat: |
3*(n-1)-17
=3*(2-1) - 17
=3* (1) - 17
=3-17
= -14 |
Du hast den Funktionsaufruf unterschlagen:
3 * Funktion1(n-1) - 17
3 * Funktion1(1) - 17 = 3 * 10 - 17 = 13
Für n=3 kannst du den Wert von Funktion1(2) verwenden und "((3 * Funktion1(2)) - 17) div 2" auswerten.
|
|
16.04.2020 17:32 |
|
|
NixJava unregistriert
|
|
Zitat: |
Wenn ich allerdings in den Taschrechner für n=3 eingebe, erhalte ich
(3*(3-1)-17) / 2
=-5,5 |
Das ist nochmal der gleiche Fehler.
Du darfst nicht einfach (3-1) einsetzen, sondern Funktion1(3-1). Und diesen Wert haben wir schon berechnet, er beträgt 13.
Zitat: |
Edit: okay. ich habe jetzt die 11 erhalten nachdem ich den wert der funktion1(2) in der ersten zeile in if eingegeben und ausgerechnet habe |
Genau!
Zitat: |
aber wieso muss ich denn so rechnen? wieso kann ich das nicht einfach so im taschenrechner wie oben für n=3 eingeben? |
Weil die rekursive Funktion so definiert wurde.
Zitat: |
Am anfang hatte ich nämlich gedacht das "Funktion1 1 = 10" eigentlich die Bedingung war wenn das Programm "beenden" soll. |
Nun ja, "Funktion1 1 = 10" ist die Abbruchbedingung. Bei dieser Rekursion ruft sich die Funktion selbst wieder auf, allerdings mit einem anderen Parameter (sonst würde man in einer Endlosschleife landen). Die natürliche Zahl n wird in jedem Durchlauf um 1 dekrementiert. Damit auch dieser Aufrufprozess endet, ist eine Abbruchbedingung nötig.
|
|
16.04.2020 22:28 |
|
|
nature6
Jungspund
Dabei seit: 16.04.2020
Beiträge: 11
|
|
danke nochmals.
ich habe das mal auf andere rekursionsbeispiele übertragen und konnte die denke ich nachvollziehen. Jetzt bin ich leider wieder an einem punkt im skript angekommen wo ich am schlauch stehe. Ich hoffe das ist kein Problem wenn es sich hierbei um listen in haskell handelt.
also im skript steht folgendes was mich verwirrt. erstmal hier der Quellcode
letztesElement :: [a] -> a
letztesElement xs = if null xs then
error "Liste ist leer"
else if null (tail xs) then head xs
else letztesElement (tail xs)
aus dem skript:
Die in Haskell vordefinierte Funktion null :: [a] -> Bool testet, ob eine Liste leer ist. Mit head, tail und null kann man beispielsweise eine Funktion definieren, die das letzte Element einer Liste extrahiert:
Für eine Liste mit mehr als einem Element ruft sich letztes Element rekursiv mit dem Schwanz der Liste auf. Enthalt die Liste nur ein Element (der Test hierfür ist null (tail xs)), so wird das erste Element dieser Liste als Ergebnis zurück geliefert (dies ist der Rekursionsanfang). Der Fehlerfall, dass die Liste gar keine Elemente enthält, wird direkt am Anfang abgefangen, und eine Fehlermeldung wird generiert. Der Typ der FunktionletztesElement ist[a] -> a, da sie eine Liste erhält (hierbei ist der konkrete Typ der Elemente egal) und ein Listenelement liefert.
im skript steht das in der zweiten if abfrage mittels der funktion "null" geprüft wird ob die liste leer ist. Wenn also null = true ist, also der hintere teil (tail xs) der liste leer ist, wird das erste element dieser liste als ergebnis zurückgeliefert.
das verstehe ich nicht. wenn im hinteren abschnitt einer liste keine elemente vorhanden sind, wie kann dann eine liste ein element ganz vorne haben? Wird eine Liste denn nicht für gewöhnlich von rechts nach links aufgefüllt?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von nature6: 17.04.2020 02:32.
|
|
17.04.2020 02:31 |
|
|
NixJava unregistriert
|
|
Zitat: |
wenn im hinteren abschnitt einer liste keine elemente vorhanden sind, wie kann dann eine liste ein element ganz vorne haben? |
Sei eine Liste [1,2,3,4] gegeben. Dann ist
code: |
1:
|
head[1,2,3,4] = 1 |
|
und
code: |
1:
|
tail[1,2,3,4] = [2,3,4] |
|
Jetzt wird die Funktion "letztesElement" jeweils rekursiv mit dem Parameter "tail[Liste]" aufgerufen, also
code: |
1:
2:
3:
4:
5:
|
letztesElement([1,2,3,4])
letztesElement(tail[1,2,3,4]) = letztesElement([2,3,4])
letztesElement(tail[2,3,4]) = letztesElement([3,4])
letztesElement(tail[3,4]) = letztesElement([4])
letztesElement(tail[4]) |
|
Im letzten Aufruf ist tail([4]) = null, also wird head[(4)] = 4 zurückgegeben und dies ist - wie gewünscht - das letzte Element der Liste.
|
|
17.04.2020 14:02 |
|
|
nature6
Jungspund
Dabei seit: 16.04.2020
Beiträge: 11
|
|
Hallo nixJava, Danke nochmals.
die (tail[4]) ist aber indem fall nicht das "x" von (x:xs) oder?
ich hatte angenommen das das erste element einer liste immer "x" ist?
meine frage bezieht sich jetzt auf die folgende aussage:
Enthalt die Liste nur ein Element (der Test hierfür ist null (tail xs)), so wird das erste Element dieser Liste als Ergebnis zurück geliefert (dies ist der Rekursionsanfang).
Ich hoffe dich stört es nicht wenn ich noch weitere fragen zum skript stelle:
eigenesHead [] = error "empty list"
eigenesHead (x:xs) = x
Die Definition von eigenes Head ist hierbei so zu interpretieren: Wenn die Eingabe eine Liste ist, die zu dem Muster (x:xs) passt (die Liste daher mindestens ein Element hat), dann gebe den zu x passenden Teil zurück und wenn die Liste zum Muster [] passt (die Liste daher leer ist) dann generiere eine Fehlermeldung. Die Fälle werden bei der Auswertung von oben nach unten geprüft. Analog ist tail definiert als.
hier eigentlich nochmal diesselbe frage. Wenn ein Element in der Liste ist. Ist doch also lediglich x gegeben? Dann passt das Muster (x:xs) doch eigentlich nicht, oder?
eigenesTail [] = error "empty list"
eigenesTail (x:xs) = xs
Eine mögliche Definition für null ist die Funktion:
eigenesNull [] = True
eigenesNull (x:xs) = False
Da die Muster von oben nach unten abgearbeitet werden, kann man alternativ auch definieren:
eigenesNull2 [] = True
eigenesNull2 xs = False
Wieso kann man hier lediglich xs benutzen? x kann ja immer noch mit einem element versehen sein? Würde doch heißen das die liste nicht leer ist?
In diesem Fall passt das zweite Muster (es besteht nur aus der Variablen xs) für jede Liste.Trotzdem wird für den Fall der leeren Liste True zurückgeliefert, da die Muster von oben nachunten geprüft werden. Falsch wird die Definition, wenn man die beiden Fälle in falscher Reihenfolge definiert:
falschesNull xs = False
falschesNull [] = True
und worin liegt hier bitte der unterschied? wieso ist die defintion in diesem fall falsch?
Da das erste Muster immer passt, wird die Funktion falschesNull für jede Liste False liefern. Der GHC iist so schlau, dies zu bemerken und liefert beim Laden der Datei eine Warnung
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von nature6: 18.04.2020 17:52.
|
|
18.04.2020 17:48 |
|
|
NixJava unregistriert
|
|
Vorab: Ich habe wenig Ahnung von Haskell und muss mir die Sachen teilweise selbst zusammenreimen. Meine Antworten sind daher als Ideen aufzufassen und sollten zusätzlich nochmal selbst durchdacht und überprüft werden.
Zitat: |
die (tail[4]) ist aber indem fall nicht das "x" von (x:xs) oder? |
Die Liste [4] lässt sich als 4 : [] (vgl. x:xs) ausdrücken, also head[4] = 4 und tail[4] = null.
Zitat: |
ich hatte angenommen das das erste element einer liste immer "x" ist? |
Ja, wenn man die Liste in der Form (x:xs) auffasst.
Zitat: |
Wenn ein Element in der Liste ist. Ist doch also lediglich x gegeben? Dann passt das Muster (x:xs) doch eigentlich nicht, oder? |
Doch, weil man die Liste [a] mit einem Element a als a : [] notieren kann.
Zitat: |
Wieso kann man hier lediglich xs benutzen? x kann ja immer noch mit einem element versehen sein? Würde doch heißen das die liste nicht leer ist? |
xs ist in diesem Fall einfach eine Variable. Ein Muster, das auf jede Liste zutrifft. xs hat in diesem konkreten Fall nichts mit dem Listenschwanz (x:xs) zu tun.
Zitat: |
und worin liegt hier bitte der unterschied? wieso ist die defintion in diesem fall falsch? |
"falschesNull xs = False" würde auch bei einer leeren Liste "False" liefern. Weil die Muster der Reihe nach bearbeitet werden, muss man zunächst "falschesNull [] = True" abfragen.
|
|
19.04.2020 12:47 |
|
|
nature6
Jungspund
Dabei seit: 16.04.2020
Beiträge: 11
|
|
|
22.04.2020 04:39 |
|
|
NixJava unregistriert
|
|
Zitat: |
z_5 + z_5-1 + z_5-2 + z_5-3 + z_5-4 + z_5-5 + z_5-6 |
Du musst mit der Notation aufpassen und Klammern setzen. Deine Schreibweise bedeutet
.
Gemeint ist aber
.
(In der Summe auf dem Screenshot sind noch b's vorhanden, die du hier nicht erwähnt hast.)
Zitat: |
wieso wird dann am ende der Reihe ein z_-m angegeben? |
Die Summe muss nicht mit dem Index "-1" enden. m ist die untere und n die obere Grenze. Es sind zwei Zahlen anzugeben. Für und also
oder in umgekehrter Reihenfolge aufgeschrieben, wie auf dem Bild. Es sollte noch erwähnt werden, was bei passiert. In diesem Fall entsteht die leere Summe, die als 0 definiert ist, also bspw.
|
|
22.04.2020 12:03 |
|
|
nature6
Jungspund
Dabei seit: 16.04.2020
Beiträge: 11
|
|
Zitat: |
Die Summe muss nicht mit dem Index "-1" enden. m ist die untere und n die obere Grenze. Es sind zwei Zahlen anzugeben. Für und also
oder in umgekehrter Reihenfolge aufgeschrieben, wie auf dem Bild.
|
Hallo nixjava. Wieso hast du bitte ab i=0 nicht mehr die -2 beibehalten? ich glaube jetzt habe ich denn Faden völlig verloren. wenn man also nun für m=-2 einsetzt, dann würde es doch wie folgt aussehen?
hab es ab 0 nicht mehr weiter ausgeführt. Wie kommst du bitte jetzt auf die -2, -1, 0, 1 usw.. im Index bzw. im Exponenten im Bezug auf n bzw. m?
|
|
22.04.2020 13:39 |
|
|
NixJava unregistriert
|
|
Ups, da ist mir ein Fehler unterlaufen: Bei sollte es heißen (habe das Minus bei i=-m nicht beachtet). Dann startet der Index bei -2. Mit würde er bei 2 starten.
Zitat: |
wenn man also nun für m=-2 einsetzt, dann würde es doch wie folgt aussehen?
|
Bei sieht es so aus: .
Mit ergibt sich .
Sorry für die Verwirrung. Ich hoffe, es ist jetzt klarer.
|
|
22.04.2020 14:27 |
|
|
nature6
Jungspund
Dabei seit: 16.04.2020
Beiträge: 11
|
|
|
22.04.2020 20:52 |
|
|
as_string
Haudegen
Dabei seit: 06.11.2013
Beiträge: 638
Herkunft: Heidelberg
|
|
Du denkst da viel zu kompliziert.
Du summierst alle auf. und i läuft von -m bis +n.
In der Aufgabe ist es nur umgekehrt geschrieben, startend mit dem größten i. Das größte i ist +n. Das zweit größte (also eins kleiner) ist dann n-1. Das nächste i, also noch ein kleiner, ist dann n-2 und so weiter.
Angenommen n ist 3 und m ist 2, dann sind Deine i der Reihe nach:
+3, +2, +1, 0, -1, -2
Sie laufen also von n bis -m und Du musst dann rechnen:
Oder Du lässt das i von -m bis +n laufen, aber bei einer Summe ist ja die Reihenfolge egal, deshalb ist es äquivalent:
Gruß
Marco
|
|
27.04.2020 16:09 |
|
|
nature6
Jungspund
Dabei seit: 16.04.2020
Beiträge: 11
|
|
vielen dank, as_String
|
|
28.04.2020 16:03 |
|
|
|