Рассмотрим следующий цикл, в котором я пока не объявлен:
while (i == i + 1) {}
Найдите определение i
, которое предшествует этому циклу, чтобы цикл while продолжался вечно.
Следующий вопрос, который задавал тот же вопрос для этого фрагмента кода:
while (i != i) {}
было очевидно для меня. Конечно, в этой другой ситуации это так, NaN
но я действительно застрял на предыдущей. Это связано с переполнением? Что заставило бы такой цикл навсегда зацикливаться в Java?
.equals()
метод? Поскольку i не объявлен, мы можем использовать любой класс, какой захотим.null
, посколькуnull == null
истинно иnull + 1
равноnull
.0.2 + 0.1 == 0.3
изменяется его значение в зависимости от настроек компилятора, фазы луны и так далее.Ответы:
Прежде всего, поскольку
while (i == i + 1) {}
цикл не меняет значениеi
, создание бесконечного цикла эквивалентно выбору значения,i
которое удовлетворяетi == i + 1
.Таких значений много:
Начнем с «экзотических»:
или
Причина соответствия этим значениям
i == i + 1
указана вJLS 15.18.2. Аддитивные операторы (+ и -) для числовых типов :
Это не удивительно, поскольку добавление конечного значения к бесконечному должно привести к бесконечному значению.
Тем не менее, большинство значений,
i
которым удовлетворяют,i == i + 1
являются просто большимиdouble
(илиfloat
) значениями:Например:
или
или
double
Иfloat
типы имеют ограниченную точность, поэтому если взять достаточно большоеdouble
илиfloat
значение, добавив1
к нему приведет к тому же значению.источник
(double)(1L<<53)
- илиfloat i = (float)(1<<24)
Эти головоломки подробно описаны в книге Джошуа Блоха и Нила Гафтера «Java Puzzlers: Traps, Pitfalls, and Corner Cases».
или:
оба приведут к бесконечному циклу, потому что добавление
1
к значению с плавающей запятой, которое достаточно велико, не изменит значение, потому что оно не «преодолевает разрыв» с его преемником 1 .Замечание по поводу второй головоломки (для будущих читателей):
также приводит к бесконечному циклу, потому что NaN не равно никакому значению с плавающей запятой, включая само 2 .
1 - Головоломки Java: ловушки, подводные камни и угловые случаи (глава 4 - Петельные головоломки).
2 - JLS §15.21.1
источник
двойной i = Double.POSITIVE_INFINITY;
источник
Просто идея: как насчет логических значений?
Разве это не случай где
i + 1 == i
?источник
+
оператора, который принимает операнды aboolean
и anint
as).