Loop aparentemente interminable termina, a menos que el Sistema.fuera.println se utiliza


Tenía un simple bit de código que se suponía que era un bucle sin fin ya que x siempre crecerá y siempre permanecerá más grande que j.

int x = 5;
int y = 9;
for (int j = 0; j < x; j++) {
   x = x + y;
}
System.out.println(y);

Pero tal como está, imprime y y no hace un bucle interminable. No puedo entender por qué. Sin embargo, cuando ajuste el código de la siguiente manera:

int x = 5;
int y = 9;
for (int j = 0; j < x; j++) {
    x = x + y;
    System.out.println(y);
}
System.out.println(y);

Se convierte en un bucle sin fin y no tengo idea de por qué. ¿Java reconoce su bucle sin fin y lo omite en la primera situación, pero tiene que ejecutar una llamada al método en el segundo por lo que se comporta como se espera? Confundido :)

Author: HopefullyHelpful, 2017-02-01

6 answers

Ambos ejemplos no son interminables.

El problema es la limitación del tipo int en Java (o casi cualquier otro lenguaje común). Cuando el valor de x alcanza 0x7fffffff, la adición de cualquier valor positivo dará lugar a un desbordamiento y el x se convierte en negativo, por lo tanto menor que j.

La diferencia entre el primer y el segundo bucle es que el código interno toma mucho más tiempo y tomaría probablemente varios minutos hasta que x se desborde. Para el primer ejemplo puede tome menos de un segundo o lo más probable es que el código será eliminado por optimizer, ya que no tiene ningún efecto.

Como se mencionó en la discusión, el tiempo dependerá en gran medida de cómo el sistema operativo almacena en búfer la salida, si se envía al emulador de terminal, etc., por lo que puede ser mucho más alto que unos pocos minutos.

 159
Author: Zbynek Vyskovsky - kvr000,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-11 13:47:25

Dado que se declaran como int, una vez que alcanza el valor máximo, el bucle se romperá a medida que el valor x se vuelva negativo.

Pero cuando el Sistema.fuera.println se agrega al bucle, la velocidad de ejecución se hace visible (ya que la salida a la consola ralentizará la velocidad de ejecución). Sin embargo, si deja que el 2do programa (el que tiene syso dentro del bucle) se ejecute durante el tiempo suficiente, debería tener el mismo comportamiento que el primero (el que no tiene syso dentro del bucle).

 33
Author: Ace Zachary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-01 05:01:32

Puede haber dos razones para esto:

  1. Java optimiza el bucle for y como no hay uso de x después del bucle, simplemente elimina el bucle. Puede comprobar esto poniendo la instrucción System.out.println(x); después del bucle.

  2. Es posible que Java no esté realmente optimizando el bucle y esté ejecutando el programa correctamente y eventualmente x crecerá demasiado para int y se desbordará. El desbordamiento de enteros probablemente hará que el entero x sea negativo que será más pequeño que j y así saldrá del bucle e imprimirá el valor de y. Esto también se puede comprobar añadiendo System.out.println(x); después del bucle.

También, incluso en el primer caso, eventualmente se producirá un desbordamiento, lo que lo convertirá en el segundo caso, por lo que nunca será un verdadero bucle sin fin.

 13
Author: Ashok Vishnoi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-01 05:07:44

Ambos no son bucles interminables, inicialmente j = 0, siempre y cuando j

Si usted está buscando un ejemplo de un bucle sin fin, debería verse así

int x = 6;

for (int i = 0; x < 10; i++) {
System.out.println("Still Looping");
}

Porque (x) nunca alcanzaría el valor de 10;

También puedes crear un bucle infinito con un bucle for doble:

int i ;

  for (i = 0; i <= 10; i++) {
      for (i = 0; i <= 5; i++){
         System.out.println("Repeat");   
      }
 }

Este bucle es infinito porque el primer bucle for dice i

 1
Author: Kennedy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-03 11:34:57

Es un bucle finito porque una vez que el valor de x excede 2,147,483,647 (que es el valor máximo de un int), x se volverá negativo y no mayor que j más, ya sea que imprima y o no.

Sólo puede cambiar el valor de y a 100000 e imprimir y en el bucle y el bucle se romperá muy pronto.

La razón por la que sientes que se volvió infinito es que el System.out.println(y); hizo que el código se ejecutara mucho más lento que sin ninguna acción.

 1
Author: Joe Cheng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-08 02:22:32

Interesante problema En realidad en ambos casos loop no es interminable

Pero la principal diferencia entre ellos es cuándo terminará y cuánto tiempo x tardará en exceder el valor máximo int que es 2,147,483,647 después de eso alcanzará el estado de desbordamiento y el bucle terminará.

La mejor manera de entender este problema es probar un ejemplo simple y preservar sus resultados.

Ejemplo:

for(int i = 10; i > 0; i++) {}
System.out.println("finished!");

Salida:

finished!
BUILD SUCCESSFUL (total time: 0 seconds)

Después de probar esto bucle infinito tardará menos de 1 segundo en terminar.

for(int i = 10; i > 0; i++) {
    System.out.println("infinite: " + i);
}
System.out.println("finished!");

Salida:

infinite: 314572809
infinite: 314572810
infinite: 314572811
.
.
.
infinite: 2147483644
infinite: 2147483645
infinite: 2147483646
infinite: 2147483647
finished!
BUILD SUCCESSFUL (total time: 486 minutes 25 seconds)

En este caso de prueba notará una gran diferencia en el tiempo que toma terminar y terminar de ejecutar el programa.

Si no tienes paciencia, pensarás que este bucle es interminable y no terminará, pero de hecho tomará horas terminar y alcanzar el estado de desbordamiento en el valor i.

Finalmente concluimos después de poner la instrucción print dentro del bucle for que tome mucho más tiempo que loop en el primer caso sin instrucción de impresión.

El tiempo necesario para ejecutar el programa depende de las especificaciones de su computadora, en particular la potencia de procesamiento(capacidad del procesador), el sistema operativo y su IDE que está compilando el programa.

Pruebo este caso en:

Lenovo 2.7 GHz Intel Core i5

Sistema operativo: Windows 8.1 64x

IDE: NetBeans 8.2

Toma alrededor de 8 horas (486 minutos) para terminar el programa.

También puede notar que el incremento de paso en el bucle for i = i + 1 es un factor muy lento para alcanzar el valor int máximo.

Podemos cambiar este factor y hacer que el incremento de paso sea más rápido para probar el bucle en menos tiempo.

Si ponemos i = i * 10 y lo probamos:

for(int i = 10; i > 0; i*=10) {
           System.out.println("infinite: " + i);
}
     System.out.println("finished!");

Salida:

infinite: 100000
infinite: 1000000
infinite: 10000000
infinite: 100000000
infinite: 1000000000
infinite: 1410065408
infinite: 1215752192
finished!
BUILD SUCCESSFUL (total time: 0 seconds)

Como ves es muy rápido en comparación con el bucle anterior

Tarda menos de 1 segundo en terminar y terminar de ejecutarse programa.

Después de este ejemplo de prueba creo que debería aclarar el problema y probar la validez de La respuesta de Zbynek Vyskovsky - kvr000, también será la respuesta a esta pregunta.

 0
Author: Oghli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-05 19:57:22