java - repetir - ¿Para qué valor de i hace while(i== i+1){} bucle para siempre?
estructura for java (4)
Considere el siguiente bucle, en el que hasta ahora no he declarado:
while (i == i + 1) {}
Encuentre la definición de
i
, que precede a este bucle, de
manera que el bucle while continúa para siempre.
La siguiente pregunta, que hizo la misma pregunta para este fragmento de código:
while (i != i) {}
era obvio para mi
Por supuesto, en esta otra situación es
NaN
pero estoy realmente atascado en la anterior.
¿Esto tiene que ver con el desbordamiento?
¿Qué causaría que un bucle así se repitiera para siempre en Java?
En primer lugar, dado que el bucle
while (i == i + 1) {}
no cambia el valor de
i
, hacer que este bucle sea infinito es equivalente a elegir un valor de
i
que satisfaga
i == i + 1
.
Hay muchos de estos valores:
Comencemos con los "exóticos":
double i = Double.POSITIVE_INFINITY;
o
double i = Double.NEGATIVE_INFINITY;
El motivo por el cual estos valores satisfacen
i == i + 1
se indica en
JLS 15.18.2.
Operadores de aditivos (+ y -) para tipos numéricos
:
La suma de un infinito y un valor finito es igual al operando infinito.
Esto no es sorprendente, ya que agregar un valor finito a un valor infinito debería resultar en un valor infinito.
Dicho esto, la mayoría de los valores de
i
que satisfacen
i == i + 1
son simplemente valores
double
(o
float
) grandes:
Por ejemplo:
double i = Double.MAX_VALUE;
o
double i = 1000000000000000000.0;
o
float i = 1000000000000000000.0f;
Los tipos de
double
y
float
tienen una precisión limitada, por lo que si toma un valor de
double
o
float
suficientemente grande, agregar
1
a esto dará como resultado el mismo valor.
Estos rompecabezas se describen en detalle en el libro "Java Puzzlers: Traps, Pitfalls, and Corner Cases" de Joshua Bloch y Neal Gafter.
double i = Double.POSITIVE_INFINITY;
while (i == i + 1) {}
o:
double i = 1.0e40;
while (i == i + 1) {}
ambos resultarán en un bucle infinito, porque agregar
1
a un valor de punto flotante que es suficientemente grande no cambiará el valor, porque no "cierra la brecha" a su sucesor
1
.
Una nota sobre el segundo enigma (para futuros lectores):
double i = Double.NaN;
while (i != i) {}
también da como resultado un bucle infinito, porque NaN no es igual a ningún valor de punto flotante, incluyéndose a sí mismo 2 .
1 - Java Puzzlers: trampas, trampas y esquinas (capítulo 4 - Loopy Puzzlers).
2 - JLS §15.21.1
Sólo una idea: ¿qué pasa con los booleanos?
bool i = TRUE;
¿No es este un caso donde
i + 1 == i
?
double i = Double.POSITIVE_INFINITY;