четверг, 30 августа 2007 г.

Java Puzzle 28: Looper

В следующих нескольких задачах авторы предлагают самим превратить некоторые циклы в бесконечные не изменяя сами циклы, а добавляя некоторые декларации перед ними.

В качестве примера рассмотрим следующий цикл:
for (int i = start; i <= start + 1; i++)

Вы думаете, что он выполнит только две итерации? Но вспомните предыдущие уроки. Следующая декларация сделает цикл бесконечным:
int start = Integer.MAX_VALUE - 1;

Теперь задание...

Сделайте цикл бесконечным:
while (i == i + 1)

Я долго думал, но так и не нашел решения. Мне кажется, что ни одной итерации не будет произведено. Я просто не подумал про числа с плавающей запятой [IEEE-754]. Помните, чему нас учили в школе? ∞ + 1 = ∞! Вот ответ:
double i = Double.POSITIVE_INFINITY;

Фактически можно использовать любое большое число, например 1.0e40. Так тоже будет работать из-за погрешности. Итак, выводы:

  • В Java возможно представить ∞ как число типа float или double. Многие удивляются, так как обычно используют целочисленную арифметику.

  • Добавление маленького числа к большому может не изменить его. Это так же неожиданно, потому что обычная арифметика это не рассматривает.

  • Компьютерная арифметика для чисел с плавающей точкой - это некоторая аппроксимация настоящей арифметики.

Java Puzzle 27: Shifty i's

Также как и в прошлый раз, тут пишут цикл со странным условием:
int i = 0;
while (-1 << i != 0) i++;
System.out.println(i);

Тот, кто написал такой цикл, думает, если при сдвиге младшие биты заполняются нулями, то эти нули сдвинутся в знаковый бит. Однако он ошибается, так реализация сдвигов в Java не выполняется последовательно на любое число бит. Для типа int дистанция вычисляется как mod 32 (для long - mod 64), что дает нам возможные значения 0...31 (или 0...63) соответственно. Следовательно, -1 << 32 == -1 << 0 == -1. А посчитать количество бит можно другим способом:
int i = 0;
for (int x = -1; x != 0; x <<= 1) i++;
System.out.println(i);

И, вообще, авторы не рекомендуют использовать переменную дистанцию для сдвига...