Intervallschachtelung in Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
DaydreamerToFu
User
Beiträge: 10
Registriert: Sonntag 29. Dezember 2013, 16:47

Sry falls ich in den falschen Themenbereich schreibe... hab leider keine andere Stelle gefunden wo ich das posten kann ^^

Also ich habe folgendes Problem:
-Wenn ich das Programm starte, kann ich nur x und y bestimmen und es geht nicht weiter.. iwie hab ichs nicht hingekriegt, das ganze mit der while-Schleife zu verbinden... :K

So sieht das ganze aus

Code: Alles auswählen

y = input ("Geben Sie die gesuchte Zahl ein: ")
x = input ("Geben Sie den ersten Wert zum teilen ein: ")
while (y !=x**2):
    if (y < x**2):
        (x**2) - 0.01
        continue
    elif (y > x**2):
        (x**2) + 0.01
        continue
    else:
        print x
        break
print "  ", x
Ich würde mich sehr über eure Hilfe freuen :D
Zuletzt geändert von Hyperion am Sonntag 29. Dezember 2013, 17:45, insgesamt 1-mal geändert.
Grund: Code in Python-Code-Tags gesetzt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Setze Python-Code doch bitte in die dafür vorgesehenen Tags; ansonsten geht u.a. die Einrückung verloren und die spielt bei Python ja ein wichtige Rolle.

Wo genau liegt denn Dein Problem? Ich meine so viel Code fällt ja nicht vom Himmel und man sollte doch meinen, dass der Einstieg in die Schleife von Dir schon mehrfach beim Testen durchlaufen worden ist! Wenn man sich die Bedingung im Kopf der Schleife anguckt, so fällt einem doch auf, dass man schon ganz spezielle Werte für ``x`` und ``y`` eingeben muss, damit die Schleife überhaupt *einmal* durchlaufen wird. Beispiel:

Code: Alles auswählen

y = 4

x = 2

y !=x**2
> False

x = 3

y !=x**2
> True
Wenn Du Python 2.x verwendest, nutze doch bitte ``raw_input`` und nicht ``input``. Das ganze umschließt Du einfach mit einem ``int(...)``, um den Rückgabewert vom Typ String in einen Integer-Wert zu wandeln.

Ich habe den Eindruck, als wäre der Code nicht von Dir und Du suchst nur jemanden, der Dir Deine Hausaufgaben macht... dazu kannst Du Dir gerne den angepinnten Thread zu diesem Thema durchlesen!

Sollte ich mich irren, so beschreib doch mal genau, *was* schief läuft. Was erwartest Du wie sich der Code bei bestimmten Eingaben verhalten soll und wie er es stattdessen wirklich tut. Du kannst auch mittels ``print`` an wichtigen Stellen Debug-Ausgaben erzeugen und Dir Werte ausgeben lassen. Das liefert Dir sicherlich wichtige Informationen, die Dir helfen zu verstehen, welcher Wert an welcher Stelle anders ist, als Du es erwartest.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
DaydreamerToFu
User
Beiträge: 10
Registriert: Sonntag 29. Dezember 2013, 16:47

Setze Python-Code doch bitte in die dafür vorgesehenen Tags; ansonsten geht u.a. die Einrückung verloren und die spielt bei Python ja ein wichtige Rolle.


Sry... habs leider nicht hingekriegt, das Bildschirmfoto hochzuladen :(

Wo genau liegt denn Dein Problem? Ich meine so viel Code fällt ja nicht vom Himmel und man sollte doch meinen, dass der Einstieg in die Schleife von Dir schon mehrfach beim Testen durchlaufen worden ist!


Naja... mir kommt es so vor, als ob das Programm nicht die Werte annimmt, die ich eingebe, denn als ich das ganze ein bisschen abgeändert habe ging es immernoch nicht ganz...

Wenn Du Python 2.x verwendest, nutze doch bitte ``raw_input`` und nicht ``input``. Das ganze umschließt Du einfach mit einem ``int(...)``, um den Rückgabewert vom Typ String in einen Integer-Wert zu wandeln.


Nee ich benutze "Editra" aufm Mac... soweit ich weiß ist "raw_input" doch für Wörter oder Buchstaben und nicht Zahlen (bin noch anfänger ^^)

Ich habe den Eindruck, als wäre der Code nicht von Dir und Du suchst nur jemanden, der Dir Deine Hausaufgaben macht... dazu kannst Du Dir gerne den angepinnten Thread zu diesem Thema durchlesen!


Nein, ich habe das alles SELBER zusammengestellt, da ich nach den Ferien ein Referat über "Iteration" halten muss, daher gibts auch keinen von dem ichs abschreiben kann (was ich sowieso nicht tun würde)

Sollte ich mich irren, so beschreib doch mal genau, *was* schief läuft. Was erwartest Du wie sich der Code bei bestimmten Eingaben verhalten soll und wie er es stattdessen wirklich tut. Du kannst auch mittels ``print`` an wichtigen Stellen Debug-Ausgaben erzeugen und Dir Werte ausgeben lassen. Das liefert Dir sicherlich wichtige Informationen, die Dir helfen zu verstehen, welcher Wert an welcher Stelle anders ist, als Du es erwartest.[/quote]

Ich will eigentlich jeden einzelnen Schritt anzeigen lassen (also wo x größer y ist oder kleiner) und eine Intervallschachtelung durchführen, jedoch kommt es mir so vor, als funktioniert das ganze noch nicht...
Nachdem ich x und y eintippe, kommt nur noch ne leere Zeile...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

DaydreamerToFu hat geschrieben: Sry... habs leider nicht hingekriegt, das Bildschirmfoto hochzuladen :(
Was für nen Bildschirmfoto? Hä? Für diesen Code braucht es doch keinen! Außerdem beziehst Du Dich auf einen Hinweis, der Dir lediglich sagt, *wie* Du Python-Code hier posten sollst! Wie haben übrigens aus extra Tags für Zitate - [ quote ] Zitat [ /quote ] ohne die Leerzeichen ;-)
DaydreamerToFu hat geschrieben: Naja... mir kommt es so vor, als ob das Programm nicht die Werte annimmt, die ich eingebe, denn als ich das ganze ein bisschen abgeändert habe ging es immernoch nicht ganz...
Wieso lässt Du Dir die Werte nicht einfach *nach* der Ausgabe und *vor* der Schleife ausgeben? ;-)

Und im übrigen kann man auch mal fixe Werte in den Code eintragen, um zu sehen, ob der Algorithmus klappt. Ich hatte Dir oben ein Beispiel gegeben (2 und 4), bei dem die Schleife auf jeden Fall betreten wird. So ein Paar kannst Du ja auch im Code angeben, um Probleme bei der Eingabe auszuschließen.
DaydreamerToFu hat geschrieben: Nee ich benutze "Editra" aufm Mac... soweit ich weiß ist "raw_input" doch für Wörter oder Buchstaben und nicht Zahlen (bin noch anfänger ^^)
Lol, sorry. Python ist doch die Sprache, die Du schreibst. Mein Hinweis bezog sich auf die *Version* des Python-Interpreters, welcher Deinen Code ausführen soll. Das wird entweder einer aus der 2.er Serie sein (2.7.x aktuell) oder aus der 3er Serie (3.3.x aktuell) sein. Aufgrund Deiner ``print``-Statements muss es ein Python 2.x sein; und da sollte man ``input`` nicht nutzen, sondern eben ``raw_input``. ``input`` *interpretiert* den eingegebenen Code und ermöglicht es so, Schad-Code in ein Programm einzuschleusen und stellt damit eine potenzielle Sicherheitslücke dar. Ich erklärte Dir ja bereits, wie Du das Ergebnis von ``raw_input`` wieder in eine Zahl verwandeln kannst.
DaydreamerToFu hat geschrieben: Nein, ich habe das alles SELBER zusammengestellt, da ich nach den Ferien ein Referat über "Iteration" halten muss, daher gibts auch keinen von dem ichs abschreiben kann (was ich sowieso nicht tun würde)
Naja, abschreiben kann man dennoch viel! Dafür dass Du den Code geschrieben haben willst, zeigst Du irgend wie wenig Ahnung von der Funktionsweise an sich und beschreibst wenig, was er tun soll...
DaydreamerToFu hat geschrieben: Ich will eigentlich jeden einzelnen Schritt anzeigen lassen (also wo x größer y ist oder kleiner) und eine Intervallschachtelung durchführen, jedoch kommt es mir so vor, als funktioniert das ganze noch nicht...
Nachdem ich x und y eintippe, kommt nur noch ne leere Zeile...
Was hast Du denn geändert? Und hat es denn vorher geklappt? Ich hatte Dir doch genügend Tipps gegeben, wie man an so ne Sache rangeht - lass Dir einfach wirklich an allen Stellen die jeweiligen Werte ausgeben. Dann siehst Du ja, ob die Schleife betreten wird und wieso darin ggf. nichts weiter gemacht wird.

Wenn Du konkretere Hilfe willst, musst Du selber mal konkreter werden... auch dazu schrieb ich Dir ja schon, was Du uns beschreiben musst.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@DaydreamerToFu: kannst Du mal ein einem Beispiel beschreiben, was Du erreichen willst? Da Du weder x noch y innerhalb der Schleife änderst, wird die Schleife ewig laufen. Ich dachte, für eine Intervallschachtelung brauchst Du eine obere und eine untere Grenze?
BlackJack

@DaydreamerToFu: Du sollst den Quelltext auch nicht als Bildschirmphoto hochladen sondern im Beitrag einfach in die entsprechenden BB-Code-Tags setzen. Es gibt da beim erstellen von Beuträgen doch diese Schaltflächen über dem Textfeld — da ist auch eins für Code. Dann wird der in einer passenden Schriftart und eingefärbt angezeigt und auch die Einrückung bleibt in der Anzeige enthalten.

Wenn Du Dir über Werte im unklaren bist, dann kannst Du die mit ``print`` ausgeben. Die `type()`- und die `repr()`-Funktion können dabei auch praktisch sein wenn man sich den Typ und eine für die Fehlersuche geeignete(re) Darstellung als Zeichenkette von Werten ausgeben lassen möchte.

Welchen Editor Du benutzt ist normalerweise unabhängig von der Python-Version. `raw_input()` ist für eingabe von Zeichenketten, deshalb musst Du das dann ja noch in eine Zahl wandeln. `input()` wertet dagegen beliebige Python-Ausdrücke aus. So etwas will man normalerweise überhaupt nicht weil der Benutzer aus versehen oder absichtlich Sachen anstellen kann die ziemlich unsicher sind und gegen die man das Programm schwer bis gar nicht absichern kann.

Leere Zeilen können eigentlich nicht kommen denn bei jedem ``print`` in dem Programm wird ja auch ein Wert ausgegeben.

Versuch ``continue`` zu vermeiden. Man kann fast alles ohne dieses Schlüsselwort ausdrücken ohne dass das Programm schwerer zu verstehen ist, IMHO sogar im Gegenteil. In Deinem Fall haben beide ``continue`` auch überhaupt gar keinen Sinn, denn das Programm verhält sich ohne genau so wie mit.

Die Klammern um die Bedingungen bei ``while`` und ``if``/``elif`` sind unnötig, die solltest Du weg lassen.

Wenn verfolgen möchtest wie sich der Wert von `x` und `y` innerhalb der Schleife entwickelt, dann musst Du *in* der Schleife dafür sorgen, dass bei jedem Schleifendurchlauf beide Werte ausgegeben werden. Hier könnte das ``continue`` übrigens auch stören weil es sehr stark einschränkt *wo* innerhalb der Schleife man etwas schreiben kann was dann auch wirklich bei jedem Durchlauf ausgeführt wird.

Die Klammern um ``x**2`` sind auch nicht nötig, denn ``**`` bindet stärker als ``-``. Python beachtet ”Punkt vor Strichrechnung” und potenzieren ist ja so eine Art Multiplikation auf Doping. ;-)

Die Schleife läuft ja so lange bis eine Bedingung mit `x` und `y` erfüllt ist. Dazu müsste sich der Wert von mindestens einem der beiden Werte innerhalb der Schleife verändern, denn sonst würde die Schleife entweder nie durchlaufen, oder aber ständig, weil sich an der Bedingung niemals etwas ändert. An welcher Stelle denkst Du denn dass Du einen Wert veränderst? Hast Du mal überprüft ob das tatsächlich der Fall ist?

Ein weiteres Problem was Du bekommen wirst ist die inheränte Ungenauigkeit von Gleitkommazahlen im Rechner. Frage: Was glaubst du was für ein Ergebnis man bekommt, wenn man mit 0 startet und dort zehn mal den Wert 0.1 drauf addiert? Probieren wir das mal aus:

Code: Alles auswählen

In [45]: n = 0

In [46]: for _ in xrange(10):
   ....:     n += 0.1
   ....: 

In [47]: n
Out[47]: 0.9999999999999999
Und überrascht‽ :-) Hier weiterlesen: http://floating-point-gui.de/

Edit: Ich bin heute einfach zuuu langsam…
DaydreamerToFu
User
Beiträge: 10
Registriert: Sonntag 29. Dezember 2013, 16:47

also ich habs jetzt nochmal versucht

wenn ichs mit einfachen Werten wie 4 und 2 versuche, klappt es einwandfrei ^^

ich hab jetzt auch noch die Werte zwischendrin anzeigen lassen, jedoch scheitert mein Programm bei Kommazahlen, z.B: 3 / 2 = ....
da kommen ständig iwelche mega-werte raus..

-das mit dem Python 2.x und 3.x, da dachte ich, du frägst ob ich das Programm von Python selbst benutze... da stand auch was von 2. ... und 3. ... (Kenn mich leider nicht so ganz aus)... Sry

Das abgeänderte sieht jetzt so aus:

Code: Alles auswählen

y = input ("Geben Sie die gesuchte Zahl ein: ")
x = input ("Geben Sie den ersten Wert zum teilen ein: ")

while (y != x**2):
    if (y < x**2):
        x = (x**2) - 0.01
        print x
        continue
    elif (y > x**2):
        x = (x**2) + 0.01
        print x
        continue
    else:
        print x
        break
print "  ", x

DaydreamerToFu
User
Beiträge: 10
Registriert: Sonntag 29. Dezember 2013, 16:47

@Black Jack

Danke für die Antwort! Ich werds sofort abändern! :D

Hab leider python programmieren ausm Internet auf die schnelle versucht zu lernen, deswegen blick ich noch nicht so ganz bei dem ganzen durch :?

ich werde versuchen deine Ratschläge zu berücksichtigen ^^
DaydreamerToFu
User
Beiträge: 10
Registriert: Sonntag 29. Dezember 2013, 16:47

Also ich hab das ganze nochmal auf einem Float-Diagramm geplant und das ganze bissl abgeändert...

Code: Alles auswählen

y = input ("Geben Sie die gesuchte Zahl ein: ")
x = input ("Geben Sie den ersten Wert zum teilen ein: ")

while y != x**2:
    if y < x**2:
        x = x**2 - 0.1
        print x
    else:
        x = x**2 + 0.1

print x
also es scheint immernoch "normal" zu laufen, wenn ich Zahlen wie 4/2 o.ä. eingebe... doch bei 3/2 kommt sowas:


Geben Sie die gesuchte Zahl ein: 3
Geben Sie den ersten Wert zum teilen ein: 2
3.9
15.11
228.2121
52080.6625864
2712395415.34
7.35708888915e+18
5.41267569229e+37
2.92970581499e+75
8.5831761624e+150
7.36709130349e+301
Traceback (most recent call last):
File "testo.py", line 4, in <module>
while y != x**2:
OverflowError: (34, 'Result too large')

ich verstehe nicht, weshalb sich die Zahl so dermaßen verändert... :S
DaydreamerToFu
User
Beiträge: 10
Registriert: Sonntag 29. Dezember 2013, 16:47

Ich hab mein Fehler gefunden.

Danke an alle für die Hilfe :)
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@DaydreamerToFu: Verzeih, aber den Algorithmus, den Du uns bisher gezeigt hast, hat nicht nur einen Fehler, sondern ist noch meilenweit von einem funktionierenden Programm entfernt. Bei einer festen Schrittweite von 0.1 wirst Du die Wurzel auch nur mit einer Genauigkeit von 0.1 finden können. Damit kann die Bedingung »y == x**2« nur in den wenigsten Fällen erfüllt werden (neben dem Problem mit der float-Genauigkeit). Zudem kann es sehr lange dauern, bis das richtige »x« gefunden wird, wenn der Startwert schlecht geraten wird. Zuletzt sehe ich immer noch kein „Intervall“. Wenn Deine Hausarbeit darum gehen soll, dann würde ich sagen, Thema verfehlt.
DaydreamerToFu
User
Beiträge: 10
Registriert: Sonntag 29. Dezember 2013, 16:47

@Sirius3

das war keine Hausaufgabe...
außerdem hab ich meinen Fehler gefunden und auch ausgebessert.. es klappt nun einwandfrei :D

Code: Alles auswählen

y = input ("Geben Sie die gesuchte Zahl ein: ")
x = input ("Geben Sie den ersten Wert zum teilen ein: ")

while y != x**2:
    if y < x**2:
        x = x - 0.1
    else:
        x = x + 0.1
print x
so sieht die verbesserte Version aus...

hab mich aber Leider bei der Intervallschachtelung vertan.. da man nicht 0.1 abzieht oder dazurechnet ^^...
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Nein, dein Programm funktioniert nicht einwandfrei. Gebe als gesuchte Zahl mal 5 ein und als Schätzwert eine 2. Dein Programm wird dann niemals aufhöhren zu rechnen.

Sirius hat dir deine Fehler doch schon alle genannt:

- Dein Programm wird in vielen Fällen schon deshalb nie eine Lösung finden, weil floats mit Ungenauigkeiten versehen sind. Daran lässt sich rein technisch gar nichts ändern. Daher wird der Vergeleich ``y != x**2`` in vielen (eigentlich in den meisten Fällen), nie erfüllt werden. floats darfst du nicht mit == vergleichen (in wenigen Ausnahmefällen natürlich schon), sondern musst immer auf ein Intervall testen: ``y-eps. <= x <= y+eps``.

- Auch wurde schon genannt, dass deine Genauigkeit nie besser als 0.1 werden wird, da du immer nur um diesen Wert änderst. Das führt im Endefekkt dazu, dass du die Gesuchte wurzel immer nur umkreist. Ist ist x um 0.03 kleiner als der gesuchte Wert, dann addierst du 0.1 drauf und im nächsten Durchlauf ist x um 0.07 größer. Daher ziehst du wieder 0.1 ab und bist wieder 0.03 kleiner und das Spiel beginnt von vorne. Du muss die Sprungweite anpassen. Wenn du einmal einen Intervall gerfunden hast, zwischen dem sich der Wert bewegt, dann musst du immer in die Mitte des Intervalls springen und links und rechts von der Mitte testen.

- Auch solltest du kein input zur Abfrage von Benutzerwerten verwenden. Damit kannst du beliebigen Python-Code ausführen, was natürlich zu schönen Problemen führen kann. Verwende raw_input und wandle das Ergebnis dann explizit mittels float um.
Das Leben ist wie ein Tennisball.
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@DaydreamerToFu: Unter einwandfrei verstehe ich etwas anderes:

Code: Alles auswählen

>>> y=16
>>> x=3
>>> while y!=x**2:
...     print x
...     if y < x**2:
...         x = x - 0.1
...     else:
...         x = x + 0.1
... 
3.0
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.8
3.9
4.0
3.9
4.0
3.9
4.0
3.9
usw.
Aber das Problem hat ja schon BlackJack geschildert. Die anderen ich in meinem vorherigen Post.
BlackJack

@DaydreamerToFu: Das klappt *nicht* einwandfrei. Lies meinen Beitrag mit der Schleife noch mal. Bei den Werten 1 und 0 bekommst Du zum Beispiel genau das Problem. Und bei vielen anderen, selbst ohne Rechenungenauigkeiten läuft das Programm auch in einer Endlosschleife, beziehungsweise bis der Wertebereich von `float` verlassen wird. Was bei *der* Schrittweite fast endlos ist. ;-)
Antworten