Comportamiento extraño del operador WHILE - página 3

 
¿Es necesario que sea WHILE mientras que podemos usar FOR?
 

cuando es esto mientras arranca y

¿cuándo es esto mientras se detiene?

while (StringHighStatus == "False" && SwingHighShift <= SwingBarCount)
 
Esto nunca será cierto (El operando ==. - Foro MQL4)
if(iFractals(NULL,0,MODE_UPPER,SwingHighShift)==iHigh(NULL,0,SwingHighShift)
por lo tanto, esto nunca se ejecuta
StringHighStatus="True";
resultando en un bucle infinito.
while(StringHighStatus=="False" || ...
  1. Si imprimieras tus variables y entradas antes y dentro de las sentencias if, te habrías dado cuenta de esto.
  2. No uses cadenas o ints cuando quieres decir booleano.
    string StringHighStatus = "False";
    while (StringHighStatus == "False" || SwingHighShift <= SwingBarCount){
       if(iFractals(NULL, 0, MODE_UPPER, SwingHighShift) == ...{
          StringHighStatus = "True";
    
    bool String HighStatus = False;
    while (!String HighStatus || SwingHighShift <= SwingBarCount){
       if(iFractals(NULL, 0, MODE_UPPER, SwingHighShift) == ...{
          String HighStatus = True;
    

 
WHRoeder:
Esto nunca será cierto (El operando ==. - Foro MQL4)
por lo tanto, esto nunca se ejecuta
resultando en un bucle infinito.

Pensé lo mismo hasta que lo probé, sorprendentemente la parte de if(double == double) sí funciona, me hace pensar si la comparación de dobles se maneja de manera diferente en las nuevas versiones.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   for(int i=0; i<100; i++)
   {if(iFractals(NULL, 0, MODE_UPPER, i) == iHigh(NULL, 0, i) && iFractals(NULL, 0, MODE_UPPER, i) > Close[0])
    Print("Fractals conditions met on bar ",i);
  }} 

EURUSD,M15: Las condiciones de los fractales se cumplen en la barra 98
EURUSD,M15: Las condiciones de los fractales se cumplen en la barra 95
EURUSD,M15: Las condiciones de los fractales se cumplieron en la barra 91
EURUSD,M15: Las condiciones de los fractales se cumplen en la barra 81
EURUSD,M15: Las condiciones de los fractales se cumplen en la barra 77
EURUSD,M15: Las condiciones de los fractales se cumplen en la barra 68
EURUSD,M15: Las condiciones de los fractales se cumplen en la barra 61
EURUSD,M15: Las condiciones de los fractales se cumplen en la barra 48
EURUSD,M15: Las condiciones de los fractales se cumplen en la barra 39
EURUSD,M15: Las condiciones de los fractales se cumplen en la barra 24
EURUSD,M15: Las condiciones de los fractales se cumplieron en la barra 19
EURUSD,M15: Las condiciones de los fractales se cumplieron en la barra 12
EURUSD,M15: Las condiciones de los fractales se cumplieron en la barra 4

 
lord_hiro:

Gracias GumRai por tu paciencia.

Tal vez esté equivocado y sea un cabeza dura pero no consigo entender la lógica...

Si el primer IF convierte, como sugieres, la cadena en "true" en digamos SwinghHighShift=10 entonces el contador no aumenta en ese ciclo; después de eso el control vuelve al WHILE: el ciclo debería terminar en este punto porque el WHILE contiene un OR lógico y una de sus condiciones se satisface.

A la inversa, si la variable se mantiene falsa el contador debería alcanzar su valor máximo y de nuevo tienes la condición de salida.

Creo que tu consideración sería cierta con un operador AND.

Siguiendo tu interpretación podría omitir el OR dentro del WHILE; podría simplemente poner la primera condición IF en la cadena: si se convierte en "true" entonces el break terminará el WHILE, de lo contrario el contador seguiría hasta su máximo.

El código se convertirá en:


Pero esto sigue siendo una solución y, lamentablemente, no explica (para mí) por qué el WHILE no se encarga del OR.

No hay nada malo con el WHILE o el OR lógico, tienes dos condiciones en tu WHILE, AMBAS deben romperse antes de que el WHILE pueda salir.

Esta es la razón por la que se atasca

  • El código entra en el bucle WHILE. Ambas condiciones son verdaderas para empezar.
  • El código recorre el bucle WHILE incrementando SwingHighShift++ hasta encontrar una barra con fractales que satisfagan las condiciones IF.
  • Tarde o temprano el código entra en los operadores IF cuando los fractales satisfacen las condiciones.
  • StringHighStatus se cambia a false para que la primera condición WHILE se rompa.
  • SwingHighShift++; NO se incrementa porque está en la parte ELSE del operador IF (la condición IF se cumplió así que ELSE se ignora).
  • La segunda condición WHILE sigue siendo verdadera por lo que el código cicla de nuevo TODAVÍA EN LA MISMA BARRA QUE LA ÚLTIMA VEZ.
  • El mismo fractal vuelve a cumplir las condiciones IF igual que la última vez.
  • El código está ahora atascado para siempre haciendo un bucle en esa barra con el fractal que cumple las condiciones IF porque SwingHighShift++ en la parte ELSE no se incrementa cuando las condiciones IF son verdaderas.

Sólo hay una pequeña posibilidad de que el bucle while pueda salir y es cuando la condición IF no se cumple para las 100 barras completas (SwingBarCount) por lo que la segunda condición WHILE se rompe antes que la primera. Entonces posteriormente los Fractales satisfacen la condición IF y se ejecuta el código para romper la 1ª condición WHILE (modificar StringHighStatus).

Necesita sacar SwingHighShift++; del ELSE y ponerlo por sí mismo en el bucle while después del operador IF para que, independientemente de lo que ocurra con las condiciones IF, siga incrementando para que el bucle pueda pasar a la siguiente barra, o utilizar break después del bloque de código de dibujo del objeto para salir del while una vez que el objeto se haya dibujado.

También necesitas darle a tu objeto una forma de crear diferentes nombres para sí mismo, de lo contrario sólo se dibujará una vez. (a no ser que quieras que sólo se dibuje una vez).

 
Volviendo a leer tus mensajes en este hilo veo donde surge tu confusión ahora. Estás pensando en la lógica de WHILE y OR al revés. El OR no se trata de detener el WHILE. Se trata de mantenerlo en marcha cuando cualquiera de las dos condiciones es válida... Es así, tienes dos luces encendidas. Tu instrucción es, Mientras la luz 1 O la luz 2 están encendidas, sigue haciendo algo. Obviamente las dos luces tienen que estar apagadas antes de dejarlas, no sólo una de ellas.
 
SDC:

Yo pensé lo mismo hasta que lo probé, sorprendentemente la parte de if(double == double) sí funciona, me hace preguntarme si la comparación de dobles se maneja de manera diferente en las nuevas construcciones.

EURUSD,M15: Condiciones de los fractales en la barra 98
EURUSD,M15: Condiciones de los fractales en la barra 95
EURUSD,M15: Condiciones de los fractales en la barra 91
EURUSD,M15: Condiciones de los fractales en la barra 81
EURUSD,M15: Condiciones de los fractales en la barra 77
EURUSD,M15: Condiciones de los fractales en la barra 68
EURUSD,M15: Condiciones fractales cumplidas en la barra 61
EURUSD,M15: Condiciones fractales cumplidas en la barra 48
EURUSD,M15: Condiciones fractales cumplidas en la barra 39
EURUSD,M15: Condiciones fractales cumplidas en la barra 24
EURUSD,M15: Condiciones fractales cumplidas en la barra 19
EURUSD,M15: Condiciones fractales cumplidas en la barra 12
EURUSD,M15: Condiciones fractales cumplidas en la barra 4


La razón por la que funciona es porque el código está comparando efectivamente el mismo valor

if(iFractals(NULL,0,MODE_UPPER,SwingHighShift)==iHigh(NULL,0,SwingHighShift) )

El buffer fractal tendrá un valor vacío o tomará su valor del máximo de la barra correspondiente.

El código es efectivamente

if(iFractals(NULL,0,MODE_UPPER,SwingHighShift)!= EMPTY_VALUE && iHigh(NULL,0,SwingHighShift==iHigh(NULL,0,SwingHighShift) 

No veo ninguna razón por la que no se pueda sustituir por

if(iFractals(NULL,0,MODE_UPPER,SwingHighShift)!= EMPTY_VALUE)
 
GumRai:

No veo ninguna razón por la que no pueda ser sustituido por

if(iFractals(NULL,0,MODE_UPPER,SwingHighShift)!= EMPTY_VALUE)
Sí, creo que es una forma mejor de hacerlo.
 
SDC:
Volví a leer tus mensajes en este hilo y veo dónde surge tu confusión ahora. Estás pensando en la lógica de WHILE y OR al revés. El OR no se trata de detener el WHILE. Se trata de mantenerlo en marcha cuando cualquiera de las dos condiciones es válida... Es así, tienes dos luces encendidas. Tu instrucción es, Mientras la luz 1 O la luz 2 están encendidas, sigue haciendo algo. Obviamente ambas luces tienen que estar apagadas antes de dejar de hacerlo, no sólo una de ellas.


Eso es todo.

Qué vergüenza... :-)

Además no es la primera vez que uso WHILE pero me puse a pensar al revés y nunca salí de MI PROPIO bucle :-/

Y así la sugerencia deVries de sustituir || por && resulta acertada.

De este tema salieron un montón de cosas más a tener en cuenta, por ejemplo donde funciona el IF( == ).

Gracias a todos por vuestra paciencia y el tiempo que habéis dedicado a hacerme entender.

 

Tendría que hacerlo así, con un break, para romper el bucle while, ¿es correcto?

  int counter=0, MaxCount = 10000;
  while( true )
     {
      Print("Counter ", counter);
      counter++;
      if( counter == MaxCount ) break;
      }