Как можно "пока (я == я);" быть бесконечным циклом в однопоточном приложении? - PullRequest
141 голосов
/ 23 января 2009

Я только что получил вопрос, на который я не могу ответить.

Предположим, у вас есть это определение цикла в Java:

while (i == i) ;

Каков тип i и значение i, если цикл не является бесконечным циклом и программа использует только один поток ?

Ответы [ 12 ]

126 голосов
/ 23 января 2009
double i = Double.NaN;

API для Double.equals () дает ответ: «Double.NaN == Double.NaN имеет значение false». Это разработано в спецификации языка Java в разделе " Типы с плавающей точкой, форматы и значения ":

NaN неупорядочено, поэтому числовой операторы сравнения <, <=, > и >= вернуть false если один или оба операнды NaN. оператор равенства == возвращает false, если любой операнд NaN, а оператор неравенства != возвращает true, если любой операнд NaN. В в частности, x!=x равно true, если и только если x равно NaN и (x<y) == !(x>=y) будет будет false, если x или y равно NaN.

30 голосов
/ 23 января 2009

Значение i тогда недопустимо. «Не число».

После некоторого поиска в Google я обнаружил, что у вас может быть NaN (не число) в Java! Итак, число с указанием числа с плавающей запятой является типом данных, а значение равно NaN. Смотри здесь

12 голосов
/ 23 января 2009
double i = Double.NaN;

NaN не равно ничему, в том числе и самому себе.

10 голосов
/ 23 января 2009
float i = Float.NaN;
while(i == i) ;
System.out.println("Not infinite!");
8 голосов
/ 28 июля 2011

Поскольку другие говорили, что это NaN, мне стало интересно узнать об официальной (JDK 6) реализации Double.isNaN, и вот:

/**
 * Returns <code>true</code> if the specified number is a
 * Not-a-Number (NaN) value, <code>false</code> otherwise.
 *
 * @param   v   the value to be tested.
 * @return  <code>true</code> if the value of the argument is NaN;
 *          <code>false</code> otherwise.
 */
static public boolean isNaN(double v) {
    return (v != v);
}
8 голосов
/ 23 января 2009

Я не уверен, но я считаю, что (i == i) не является атомарной операцией в многопоточном процессе, поэтому, если значение i будет изменено другим потоком в промежутках между его значениями, которые будут помещены в поток, выполняющий цикл, то это условие может быть ложным.

2 голосов
/ 23 января 2009

Я бы добавил

float i = Float.NaN;

а также

double i = Double.NaN;

Обычный трюк в подобных вопросах - допущение, что вы - int. Другие распространенные предположения: s - строка, x, y - двойное число, ch - символ, b - байт и т. Д. Если вы видите такой вопрос, вы можете поспорить, что «i» не соответствует его типу.

Аналогичный вопрос есть; Это никогда не зацикливается, что такое «х»

while(x == x && x != x + 0) { }

Еще один вопрос, который мне очень нравится; Этот цикл представляет собой бесконечный цикл, каковы возможные значения х. (: Я считаю двенадцать из них:)

while(x != 0 && x == -x) { }
2 голосов
/ 23 января 2009

Думайте о Нане как об эквиваленте исключения, но используйте магическое значение в расчете. Поскольку расчет не удался - например, квадратный корень из отрицания, деление на ноль и т. Д. - нет смысла сравнивать их с чем-либо еще. В конце концов, если делить на ноль - это нан, это эквивалентно квадратному корню из -2 или квадратному корню из -3?

Nan позволяет выполнить вычисление, которое включает в себя этап, который возвращает неверный ответ, чтобы завершить его без введения дополнительных исключений. Чтобы убедиться, что ответ - это значение, просто протестируйте его на отсутствие nandness (это слово, если я его не упаковал) через Float.isNan () или эквивалент.

0 голосов
/ 28 июля 2011

Не бесконечный цикл, одна нить:)

import static B.*;
public class A {
    public static void main(String[] args) {
        System.out.println("Still Running");
        while (i == i) ;
    }
}


public class B {

    public static int i;
    static {
        System.exit(0);
    }
}
0 голосов
/ 28 июля 2011

i == i не является атомарным. Проверено такой программой:

static volatile boolean i = true;
public static void main(String[] args) throws InterruptedException
{
    new Thread() {
        @Override
        public void run() {
            while (true) {
                i = !i;
            }
        }
    }.start();

    while (i == i) ;
    System.out.println("Not atomic! i: " + i);
}

Обновление Вот еще один пример не бесконечного цикла (новые потоки не создаются).

public class NoNewThreads {
    public static void main(String[] args) {
        new NoNewThreads();
        System.gc();
        int i = 500;
        System.out.println("Still Running");
        while (i == i) ;
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        Thread.sleep(1000);
        System.exit(0);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...