1. Обзор
Проще говоря, NaN - это числовое значение типа данных, которое означает «не число».
В этом кратком руководстве мы объясним значение NaN в Java и различные операции, которые могут создавать или задействовать это значение.
2. Что такое NaN ?
NaN обычно указывает на результат неверных операций. Например, попытка разделить ноль на ноль - одна из таких операций.
Мы также используем NaN для непредставимых значений. Квадратный корень из -1 - один из таких случаев, поскольку мы можем описать значение ( i ) только в комплексных числах.
Стандарт IEEE для арифметики с плавающей точкой (IEEE 754) определяет значение NaN . В Java типы float и double реализуют этот стандарт.
Java определяет константы NaN для типов float и double как Float .NaN и Double.NaN :
« Константа, содержащая значение Not-a-Number (NaN) типа double. Это эквивалентно значению, возвращаемому Double.longBitsToDouble (0x7ff8000000000000L) ».
и:
«Константа, содержащая не-числовое (NaN) значение типа float. Это эквивалентно значению, возвращаемому Float.intBitsToFloat (0x7fc00000) ».
У нас нет этого типа констант для других числовых типов данных в Java.
3. Сравнение с NaN
При написании методов на Java мы должны проверять, что ввод действителен и находится в ожидаемом диапазоне. В большинстве случаев значение NaN не является допустимым вводом. Следовательно, мы должны убедиться, что входное значение не является значением NaN, и правильно обработать эти входные значения.
NaN нельзя сравнивать ни с одним значением плавающего типа. Это означает, что мы получим false для всех операций сравнения с NaN (кроме «! =», Для которого мы получаем true ).
Мы получаем истину для « x! = X» тогда и только тогда, когда x равен NaN:
System.out.println("NaN == 1 = " + (NAN == 1)); System.out.println("NaN > 1 = " + (NAN > 1)); System.out.println("NaN < 1 = " + (NAN NaN = " + (NAN > NAN)); System.out.println("NaN < NaN = " + (NAN < NAN)); System.out.println("NaN != NaN = " + (NAN != NAN));
Давайте посмотрим на результат выполнения приведенного выше кода:
NaN == 1 = false NaN > 1 = false NaN NaN = false NaN < NaN = false NaN != NaN = true
Следовательно, мы не можем проверить NaN путем сравнения с NaN с помощью «==» или «! =». Фактически, нам редко следует использовать операторы «==» или «! =» С типами float или double .
Вместо этого мы можем использовать выражение « x! = х » . Это выражение возвращает истину только для NAN.
Мы также можем использовать методы Float.isNaN и Double.isNaN для проверки этих значений . Это предпочтительный подход, поскольку он более читабелен и понятен:
double x = 1; System.out.println(x + " is NaN = " + (x != x)); System.out.println(x + " is NaN = " + (Double.isNaN(x))); x = Double.NaN; System.out.println(x + " is NaN = " + (x != x)); System.out.println(x + " is NaN = " + (Double.isNaN(x)));
При запуске этого кода мы получим следующий результат:
1.0 is NaN = false 1.0 is NaN = false NaN is NaN = true NaN is NaN = true
4. Операции, производящие NaN
Выполняя операции с типами float и double , мы должны знать значения NaN .
Некоторые методы и операции с плавающей запятой производят значения NaN вместо выдачи исключения. Нам может потребоваться явная обработка таких результатов.
Обычным случаем, приводящим к не- числовым значениям, являются математически неопределенные числовые операции :
double ZERO = 0; System.out.println("ZERO / ZERO = " + (ZERO / ZERO)); System.out.println("INFINITY - INFINITY = " + (Double.POSITIVE_INFINITY - Double.POSITIVE_INFINITY)); System.out.println("INFINITY * ZERO = " + (Double.POSITIVE_INFINITY * ZERO));
Эти примеры приводят к следующему результату:
ZERO / ZERO = NaN INFINITY - INFINITY = NaN INFINITY * ZERO = NaN
Числовые операции, которые не приводят к действительным числам, также дают NaN:
System.out.println("SQUARE ROOT OF -1 = " + Math.sqrt(-1)); System.out.println("LOG OF -1 = " + Math.log(-1));
Эти утверждения приведут к:
SQUARE ROOT OF -1 = NaN LOG OF -1 = NaN
Все числовые операции с NaN в качестве операнда в результате дают NaN :
System.out.println("2 + NaN = " + (2 + Double.NaN)); System.out.println("2 - NaN = " + (2 - Double.NaN)); System.out.println("2 * NaN = " + (2 * Double.NaN)); System.out.println("2 / NaN = " + (2 / Double.NaN));
И результат вышеизложенного:
2 + NaN = NaN 2 - NaN = NaN 2 * NaN = NaN 2 / NaN = NaN
Наконец, мы не можем назначить нуль для двойного или поплавковых переменного типа. Вместо этого мы можем явно назначить NaN таким переменным, чтобы указать отсутствующие или неизвестные значения:
double maxValue = Double.NaN;
5. Заключение
В этой статье мы обсудили NaN и различные операции с ним. Мы также обсудили необходимость обработки NaN при явном выполнении вычислений с плавающей запятой в Java.
Полный исходный код можно найти на GitHub.