Das OFFIZIELLE PROFAN SUPPORT FORUM
Einsteigerfragen
PROFAN-Programmierung
Helfer & Tools
Anregungen & Vorschläge
PROFAN-NEWS
Die Regeln!
1 - Einsteigerfragen

 Neues Thema  |  Zur Übersicht  |  Suchen  |  Einloggen   Neuerer Beitrag  |  Älteres Thema 
 While- Bedingung
Autor: Karl-Jürgen Hilger (---.dyn.telefonica.de)
Datum:   25.07.15 13:36

Hallo,

ich habe ein Problem mit While- Bedingungen, das ich nicht klären kann.

Es soll in Schritten von einem Zehntel von 0 bis 1 gezählt werden.
Der Wert 1 ist die Bedingung für den Abbruch der Schleife.
Demnach ist 0.9 der letzte gültige Wert für einen Durchlauf der Schleife.

In meinem Beispiel habe ich das in 2 Variationen umgesetzt, die beide fehlschlagen.

Variation 1 "bemerkt" die Abbruch-Bedingung nicht und läuft ewig weiter.
Variation 2 macht noch einen Schleifendurchlauf, obwohl die Bedingung nicht mehr gegeben ist.

Daß beide Variationen aber logisch richtig sind, kann man einfach prüfen, indem man keine Brüche benutzt.
Zum Beispiel:

zeit.aktuell = 0
zeit.schritt = 1
zeit.stopbedingung = 10

Nun arbeiten beide Variationen korrekt von 0-9.
Wo liegt mein Fehler?
XProfan- Version ist die aktuelle X3.

Gruß
KJ

 CLS
 
 Declare Double zeit.aktuell, \
                zeit.schritt, \
                zeit.stopbedingung
 
 zeit.aktuell        = 0
 zeit.schritt        = 0.1
 zeit.stopbedingung  = 1.0
 
 var Integer true = 1
 
 // Bitte Variation_1 oder Variation_2 aktivieren
 Variation_1
 //Variation_2
 
 WaitInput
 
 Proc Variation_1
   While true
     zeige_abgelaufene_zeit
     zeit.aktuell = zeit.aktuell + zeit.schritt
     true = (zeit.aktuell <> zeit.stopbedingung)//
   EndWhile
 EndProc
 
 Proc Variation_2
   While zeit.aktuell < zeit.stopbedingung
     zeige_abgelaufene_zeit
     zeit.aktuell = zeit.aktuell + zeit.schritt
   EndWhile
 EndProc
 
 Proc zeige_abgelaufene_zeit
   Locate 15,35
   Print zeit.aktuell
   Sleep 1000
 EndProc
 




Nachricht bearbeitet (25.07.15 14:33)

Beitrag beantworten
 
 Re: While- Bedingung
Autor: Heinz Brill (---.dip0.t-ipconnect.de)
Datum:   25.07.15 14:58

Zitat:


true = (zeit.aktuell <> zeit.stopbedingung)


Das wird sowieso immer 1 ergeben und eine Endlosschleife
entsteht.
Außerdem mischt du einen Integer mit Double-Werten.

Wenn Start, Stop und Schrittweite doch bekannt sind,
nimm doch einfach eine WhileLoop - Schleife.

 Cls
 Set("Decimals", 2)
 WhileLoop 1, 9
   Print (&LOOP / 10)
 EndWhile
 WaitKey
 End
 


Oder baue die 1 Variante entsprechend um.
Ich denke mal, daß das so überschaubarer wäre :

 Proc Variation_1
  While (zeit.aktuell < zeit.stopbedingung)
      zeige_abgelaufene_zeit
      zeit.aktuell = zeit.aktuell + zeit.schritt
  EndWhile  
 EndProc
 


Obwohl auch hier 1 Schritt zuviel gezählt wird.
Oder machen wir beide da einen Denkfehler ?

H.Brill
XProfan X4 + FreeProfan

Nachricht bearbeitet (25.07.15 15:29)

Beitrag beantworten
 
 Re: While- Bedingung
Autor: Karl-Jürgen Hilger (---.dyn.telefonica.de)
Datum:   25.07.15 16:01

Hi Heinz,

erstmal danke, daß Du es dir angesehen hast.

Deine Punkte seh' ich so:

Ich glaube nicht, daß ich Integer- und Double- Werte vermische, da "true" ein Wahrheitswert ist, der sich nicht aus Berechnungen mit Double-Variablen ergibt.
Er enthält 1 oder 0, je nach Gültigkeit des überprüften Ausdrucks.
Daher hätte ich genausogut Strings überprüfen können, z.B.
true = (meinstring = "Hallo")

Und so bleibt "true" eben nicht immer 1, da der geprüfte Ausdruck unweigerlich falsch werden muß, wenn beide Variablen den Wert 1,0 haben.

Für den Zweifelsfall schlug ich daher vor, es mal ohne Bruchzahlen zu versuchen, weil man dann sieht, daß alles korrekt funktioniert.


Was hälst Du denn von dem auffälligen Fehler in Variation 2?
Dort hält die While-Schleife die einfache Bedingung x < y nicht ein, und macht noch einen Durchlauf,
obwohl x schon gleich y ist.

Das kann doch definitv nicht richtig sein?

Gruß
KJ



Beitrag beantworten
 
 Re: While- Bedingung
Autor: Heinz Brill (---.dip0.t-ipconnect.de)
Datum:   25.07.15 16:27

Beim Wahrheitswert dachte ich da an
die XProfans interne Umwandlung, die
dann bei einer Zuweisung zweier verschiedener
Variablen greift.
Auf jeden Fall ist, wenn ich true unten in
der Proc
zeige_abgelaufene_zeit
ausprinte, immer 1.

Den Fehler in Variation 2 habe ich dir ja oben
schon bestätigt. Woran das nun hängt, muß
man noch ausprobieren.

H.Brill
XProfan X4 + FreeProfan

Nachricht bearbeitet (25.07.15 16:36)

Beitrag beantworten
 
 Re: While- Bedingung
Autor: RGH (---.hsi.kabel-badenwuerttemberg.de)
Datum:   25.07.15 18:25

Hallo Karl-Jürgen,

das Problem bei der ganzen Sache ist, dass sich nicht alle Double-Werte 100%ig exakt binär darstellen lassen. Von daher ist ein Vergleich auf Gleichheit oder Ungleichheit immer problematisch. Wenn Du das Programm wie folgt erweiterst, siehst Du, was ich meine:

CLS
 Decimals 20
 
  Declare Double zeit.aktuell, \
                 zeit.schritt, \
                 zeit.stopbedingung
  
  zeit.aktuell        = 0
  zeit.schritt        = 0.1
  zeit.stopbedingung  = 1.0
  
  var Integer true = 1
  
  // Bitte Variation_1 oder Variation_2 aktivieren
  Variation_1
  //Variation_2
  
  WaitInput
  
  Proc Variation_1
    While true
      zeige_abgelaufene_zeit
      zeit.aktuell = zeit.aktuell + zeit.schritt
      true = (zeit.aktuell <> zeit.stopbedingung)//
    EndWhile
  EndProc
  
  Proc Variation_2
    While zeit.aktuell < zeit.stopbedingung
      zeige_abgelaufene_zeit
      zeit.aktuell = zeit.aktuell + zeit.schritt
    EndWhile
  EndProc
  
  Proc zeige_abgelaufene_zeit
    Locate 15,35
    Print zeit.aktuell
    Locate 16,35
    Print zeit.stopbedingung
    Sleep 1000
  EndProc


Ich habe die Darstellungsgenauigkeit auf 20 Stellen erhöht (15 würden auch reichen) und gebe auch die Zeit der Stop-Bedingung aus.

In Variation_1 sind beide Werte nie 100%ig gleich, daher läuft es ewig. In Variation_2 ist nach dem neunten Schritt die aktuelle Zeit in ener der hinteren Stellen eben immer noch kleiner, daher greift die Bedingung erst in der nächsten Runde.

Um diese Problematik zu umgehen kann man z.B. die extra dafür geschaffene Funktion "nearly" verwenden (siehe XProfan-Hilfe), Ersetzt Du z.B. in Variation 1 die Vergleichszeile durch
true = not(nearly(zeit.aktuell, zeit.stopbedingung, 2))
, klappt es wie gewünscht, da hier der Vergleich mit den auf zwei Stellen nach dem Komma gerundeten Werten durchgeführt wird. Für Variante_2 erweiterst Du den Vergleich mit der Funktion "round" (im Beispiel werden auch zwei Nachkommastellen genutzt):
While round(zeit.aktuell,2) < round(zeit.stopbedingung,2)


Ich weiß, das ist eine böse Falle in nahezu allen Programmiersprachen, die Fließkommazahlen als double oder single darstellen. Das hat mir in meinem Berufsleben als System-Programmierer schon manches graues Haar verursacht.

Gruß
Roland

Offizielle Homepage: http://www.xprofan.de
Der neue PROFAN-FAN-SHOP: http://www.spreadshirt.de/shop.php?sid=9330
Das kostenlose Kartenspiel: http://www.rgh-soft.de/sprace/sprace.htm

Beitrag beantworten
 
 Re: Danke
Autor: Karl-Jürgen Hilger (---.dyn.telefonica.de)
Datum:   25.07.15 19:46

Hallo Roland,

ich danke Dir ganz herzlich für Deine ausführliche Erklärung.
Damit kann ich sehr gut weiterarbeiten.

Gruß
KJ



Beitrag beantworten
 
 Re: While- Bedingung
Autor: Michael Wodrich (91.106.186.---)
Datum:   27.07.15 01:05

Das Umdrehen der Abfrage kann auch helfen, also Repeat...Until stattdessen nehmen.

--
Programmieren, das spannendste Detektivspiel der Welt.
Programmierumgebung: | XProfan (neueste) | Win (neueste)


Beitrag beantworten
 Foren-Liste  |  Baumstruktur   Neuerer Beitrag  |  Älteres Thema 


 Foren-Liste  |  Zur Registrierung 
 Benutzerlogin
 Benutzername:
 Passwort:
 Login-Daten speichern:
   
 Passwort vergessen?
E-Mail-Adresse oder Username unten eingeben. Dann wird Dir per e-Mail ein neues Passwort zugeschickt.

phorum.org