NaN в Java

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.