NaN - NaN

В вычисление, NaN, стоя для Не число, является членом числового тип данных что можно интерпретировать как ценность что не определено или непредставимо, особенно в арифметика с плавающей запятой. Систематическое использование NaN было введено IEEE 754 стандарт с плавающей запятой в 1985 году, а также представление других нефинитных величин, таких как бесконечности.

В математика, ноль делится на ноль не определен как настоящий номер, и поэтому в вычислительных системах представлен NaN. В квадратный корень из отрицательное число это не настоящий номер, и поэтому также представлен NaN в совместимых вычислительных системах. NaN также могут использоваться для представления отсутствующих значений в вычислениях.[1][2]

Предусмотрены два отдельных типа NaN, называемых тихие NaN и сигнализация NaN. Тихие NaN используются для распространения ошибок, вызванных недопустимыми операциями или значениями. Сигнальные числа NaN могут поддерживать расширенные функции, такие как числовое смешивание и символьное вычисление или другие расширения базовой арифметики с плавающей запятой.

Плавающая точка

В вычислениях с плавающей запятой NaN не то же самое, что бесконечность, хотя оба обычно обрабатываются как особые случаи в представлениях вещественных чисел с плавающей запятой, а также в операциях с плавающей запятой. Недействительная операция также не то же самое, что арифметическое переполнение (который может вернуть бесконечность) или арифметическое истощение (который вернет наименьшее нормальный номер, а денормальное число, или нуль ).

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

Например, побитовый IEEE с плавающей точкой стандартная одинарная точность (32 бита) NaN будет

s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx

где s знак (чаще всего игнорируется в приложениях) и Икс последовательность представляет собой ненулевое число (нулевое значение кодирует бесконечности). Первый бит из Икс используется для определения типа NaN: «тихий NaN» или «сигнальный NaN». Остальные биты кодируют полезная нагрузка (чаще всего игнорируется в приложениях).

Операции с плавающей запятой, отличные от упорядоченных сравнений, обычно передают тихий NaN (qNaN). Большинство операций с плавающей запятой для сигнализации NaN (sNaN) сигнализировать об исключении недопустимой операции; тогда действие исключения по умолчанию такое же, как и для операндов qNaN, и они производят qNaN, если производят результат с плавающей запятой.

Распространение тихих NaN с помощью арифметических операций позволяет обнаруживать ошибки в конце последовательности операций без тщательного тестирования на промежуточных этапах. Например, если кто-то начинает с NaN и добавляет 1 пять раз подряд, каждое добавление приводит к NaN, но нет необходимости проверять каждое вычисление, потому что можно просто отметить, что окончательный результат - NaN. Однако, в зависимости от языка и функции, NaN можно незаметно удалить из цепочки вычислений, в которой одно вычисление в цепочке даст постоянный результат для всех других значений с плавающей запятой. Например, расчет Икс0 может дать результат 1, даже если Икс является NaN, поэтому проверка только окончательного результата может скрыть тот факт, что вычисление перед Икс0 привело к NaN. В общем, значит, более поздний тест для набора недействительным флаг необходим для обнаружения всех случаев, когда вводятся NaN[3] (увидеть Определение функции ниже для получения дополнительной информации).

В разделе 6.2 старого IEEE 754-2008 стандартно, есть две аномальные функции ( maxNum и minNum функции, которые возвращают максимум два операнда, которые, как ожидается, будут числами), которые предпочитают числа - если только один из операндов является NaN, то возвращается значение другого операнда. В IEEE 754-2019 ревизия заменила эти функции, поскольку они не ассоциативный (когда в операнде появляется сигнальный NaN).[4][5]

Сравнение с NaN

Сравнение с NaN всегда возвращает неупорядоченный результат даже если сравнивать с собой. Предикаты сравнения либо сигнализируют, либо не сигнализируют о тихих операндах NaN; версии сигнализации сигнализируют об исключении недопустимой операции для таких сравнений. Предикаты равенства и неравенства не сигнализируют, поэтому Икс = Икс возврат false может использоваться для проверки того, Икс тихий NaN. Все другие стандартные предикаты сравнения сигнализируют о получении операнда NaN. Стандарт также предоставляет несигнальные версии этих других предикатов. Предикат isNaN (Икс) определяет, является ли значение NaN, и никогда не сигнализирует об исключении, даже если Икс сигнальный NaN.

Сравнение NaN и любого значения с плавающей запятой Икс (включая NaN и ± ∞)
СравнениеNaN ≥ ИксNaN ≤ ИксNaN> ИксNaN < ИксNaN = ИксNaN ≠ Икс
РезультатВсегда ЛожьВсегда ЛожьВсегда ЛожьВсегда ЛожьВсегда ЛожьВсегда Правда

Операции, генерирующие NaN

Есть три типа операций, которые могут возвращать NaN:[6]

  • Большинство операций хотя бы с одним операндом NaN.
  • Неопределенные формы:
    • Подразделения (±0) / (±0) и (±∞) / (±∞).
    • Умножения (±0) × (±∞) и (±∞) × (±0).
    • Остаток Икс % у когда Икс это бесконечность или у равно нулю.
    • Дополнения (+∞) + (−∞), (−∞) + (+∞) и эквивалентные вычитания (+∞) − (+∞) и (−∞) − (−∞).
    • В стандарте есть альтернативные функции для полномочий:
      • Стандарт пау функция и целочисленная экспонента пух функция определить 00, 1, и 0 так как 1.
      • В Powr функция определяет все три неопределенные формы как недопустимые операции и поэтому возвращает NaN.
  • Реальные операции с сложный результаты, например:

NaN также могут быть явно присвоены переменным, обычно как представление отсутствующих значений. До стандарта IEEE программисты часто использовали специальные значения (например, -99999999) для представления неопределенных или отсутствующих значений, но не было гарантии, что они будут обрабатываться последовательно или правильно.[1]

NaN не обязательно генерируются во всех вышеупомянутых случаях. Если операция может вызвать исключительную ситуацию и ловушки не замаскированы, тогда операция вызовет ловушку.[7] Если операнд является тихим NaN, а также нет сигнального операнда NaN, тогда нет условия исключения и результатом является тихий NaN. Явные присвоения не вызовут исключения даже для сигнализации NaN.

Тихий NaN

Тихие NaN или qNaN не вызывают каких-либо дополнительных исключений, поскольку они распространяются через большинство операций. Исключение составляют случаи, когда NaN нельзя просто передать в неизмененном виде на вывод, например, при преобразовании формата или некоторых операциях сравнения.

Сигнализация NaN

Сигнальные NaN, или sNaN, представляют собой особые формы NaN, которые при использовании большинством операций должны вызывать исключение недопустимой операции, а затем, при необходимости, «успокаиваться» в qNaN, который затем может распространяться. Они были представлены в IEEE 754. Было несколько идей, как их можно использовать:

  • Заполнение неинициализированной памяти сигнальными NaN приведет к возникновению исключения недопустимой операции, если данные используются до инициализации.
  • Использование sNaN в качестве заполнителя для более сложных объект, такие как:

При обнаружении обработчик прерывания может декодировать sNaN и вернуть индекс для вычисленного результата. На практике такой подход сталкивается со многими сложностями. Лечение знаковый бит NaN для некоторых простых операций (например, абсолютная величина ) отличается от такового для арифметических операций. Стандарт не требует ловушек. Есть и другие подходы к такого рода проблемам, которые были бы более переносимыми.

Определение функции

Существуют различные мнения о правильном определении результата числового функция который получает на входе тихий NaN. Одно из мнений состоит в том, что NaN должно распространяться на выход функции во всех случаях, чтобы распространять индикацию ошибки. Другой взгляд, сделанный ISO C99 и IEEE 754-2008 стандартов в целом заключается в том, что если функция имеет несколько аргументов и вывод однозначно определяется всеми входами, отличными от NaN (включая бесконечность), то это значение должно быть результатом. Так, например, значение, возвращаемое гипотеза (± ∞, qNaN) и гипотеза (qNaN, ± ∞) равно + ∞.

Проблема стоит особенно остро для возведение в степень функция пау (Икс, у) = Иксу. Выражения 00, ∞0 и 1 считаются неопределенные формы когда они встречаются как пределы (как и ∞ × 0), и вопрос о том, от нуля до нулевой степени следует определить как 1 разделившееся мнение.

Если вывод считается неопределенным, когда параметр не определен, тогда pow (1, qNaN) должен произвести qNaN. Однако, математические библиотеки обычно возвращают 1 для pow (1, у) для любого настоящий номер у, и даже когда у является бесконечность. Точно так же они производят 1 для пау (Икс, 0) даже когда Икс равно 0 или бесконечности. Обоснованием для возврата значения 1 для неопределенных форм было то, что значение функций в особых точках может быть принято как конкретное значение, если это значение находится в пределе значения[требуется разъяснение ] для всех, кроме исчезающе маленькой части шара вокруг предельного значения параметров. Версия 2008 г. IEEE 754 стандарт говорит, что pow (1, qNaN) и pow (qNaN, 0) оба должны возвращать 1, поскольку они возвращают 1 все, что используется вместо тихого NaN. Более того, ISO C99, а затем IEEE 754-2008 решили указать pow (-1, ± ∞) = 1 вместо qNaN; Причина этого выбора приводится в обосновании языка C.[8] "Как правило, C99 избегает результата NaN, когда полезно числовое значение. ... Результат pow (−2, ∞) равно + ∞, потому что все большие положительные значения с плавающей запятой являются целыми числами ".

Чтобы удовлетворить тех, кто желает более строгой интерпретации того, как должна действовать степенная функция, стандарт 2008 определяет две дополнительные степенные функции: pown (Икс, п), где показатель степени должен быть целым числом, и Powr (Икс, у), который возвращает NaN всякий раз, когда параметр является NaN или возведение в степень дало бы неопределенная форма.

Целое число NaN

Самый фиксированный размер целое число форматы не могут явно указывать недопустимые данные. В таком случае при преобразовании NaN в целочисленный тип IEEE 754 стандарт требует, чтобы недопустимая операция исключение сигнализировать. Например в Ява, такие операции вызывают экземпляры java.lang.ArithmeticException.[9] В C, они приводят к неопределенное поведение, но если приложение F поддерживается, операция приводит к «недопустимой» исключительной ситуации с плавающей запятой (как того требует стандарт IEEE) и неопределенному значению.

Perl с Math :: BigInt пакет использует «NaN» для результатов строк, не представляющих действительные целые числа.[10]

> perl -mMath :: BigInt -e "print Math :: BigInt-> new ('foo')"NaN

Дисплей

Различные операционные системы и языки программирования могут иметь разные строковые представления NaN.

nanNaNNaN% NANNaNQNaNSqNaNsNaN1. # SNAN1. # QNAN-1. # IND + nan.0

Поскольку на практике закодированные NaN имеют знак, бит молчания / сигнализации и необязательную диагностическую информацию (иногда называемую полезная нагрузка), они также часто встречаются в строковых представлениях NaN, например:

-NaN NaN12345-sNaN12300-NaN (s1234)

(существуют другие варианты).

Кодирование

В IEEE 754 соответствующие стандарту форматы хранения с плавающей запятой, NaN идентифицируются с помощью определенных заранее заданных битовых шаблонов, уникальных для NaN. Знаковый бит не имеет значения. Двоичный формат NaN представлены экспоненциальным полем, заполненным единицами (например, значениями бесконечности), и некоторым ненулевым числом в значении поля (чтобы отличить их от значений бесконечности). Исходный стандарт IEEE 754 1985 г. (IEEE 754-1985 ) описывал только двоичные форматы с плавающей запятой и не указывал, как должно быть помечено состояние сигнализации / молчания. На практике старший бит значимого поля определяет, является ли NaN сигнальным или нет. В результате были получены две разные реализации с обратным смыслом:

  • большинство процессоров (в том числе Intel и AMD с x86 семья, Семейство Motorola 68000, то Цель PowerPC семья, РУКА семья, солнце SPARC семейный, и по желанию новый MIPS процессоры) устанавливают бит сигнализации / молчания в ненулевое значение, если NaN является тихим, и в ноль, если NaN сигнализирует. Таким образом, на этих процессорах бит представляет собой is_quiet флаг;
  • в NaN, порожденных PA-RISC и в старых процессорах MIPS бит сигнализации / молчания равен нулю, если NaN является тихим, и ненулевым, если NaN сигнализирует. Таким образом, на этих процессорах бит представляет собой is_signaling флаг.

Первый вариант был предпочтительнее, поскольку он позволяет реализации заглушить сигнальный NaN, просто установив бит сигнализации / молчания в 1. Обратное невозможно с последним выбором, поскольку установка бита сигнализации / молчания в 0 может дать бесконечность.[11]

Редакция 2008 г. стандарта IEEE 754 (IEEE 754-2008 ) дает формальные рекомендации по кодированию состояния сигнализации / молчания.

  • Для двоичных форматов наиболее значимым битом значимого поля должен быть is_quiet флаг. То есть этот бит не равен нулю, если NaN неактивен, и нулю, если NaN сигнализирует.
  • Для десятичных форматов, как в двоичном, так и в десятичном кодировании, NaN идентифицируется по тому, что верхние пять битов поля комбинации после знакового бита установлены в единицы. Шестой бит поля - это is_quiet флаг. Стандарт следует интерпретации как is_signaling флаг. То есть бит сигнализации / молчания равен нулю, если NaN является тихим, и ненулевым, если NaN сигнализирует. Сигнализация NaN прекращается очисткой шестого бита.

Для соответствия IEEE 754-2008 значение бита сигнализации / молчания в последних процессорах MIPS теперь можно настраивать через поле NAN2008 регистра FCSR. Эта поддержка не является обязательной в MIPS Release 3 и требуется в Release 5.[12]

Состояние / значение остальных битов значимого поля не определены стандартом. Это значение называется «полезной нагрузкой» NaN. Если операция имеет единственный вход NaN и передает его на выход, полезная нагрузка результата NaN должна быть полезной нагрузкой входного NaN (это не всегда возможно для двоичных форматов, когда состояние сигнализации / молчания кодируется с помощью is_signaling flag, как описано выше). Если имеется несколько входов NaN, полезная нагрузка результата NaN должна быть из одного из входных NaN; в стандарте не указано, какие именно.

использованная литература

  1. ^ а б Боуман, Кеннет (2006). Введение в программирование с IDL: интерактивный язык данных. Академическая пресса. п.26. ISBN  978-0-12-088559-6.
  2. ^ Press, William H .; Teukolsky, Saul A .; Веттерлинг, Уильям Т .; Фланнери, Брайан П. (2007). Числовые рецепты: искусство научных вычислений. Издательство Кембриджского университета. п.34. ISBN  978-0-521-88068-8.
  3. ^ Уильям Кахан (1 октября 1997 г.). «Лекционные заметки о статусе стандарта IEEE 754 для двоичной арифметики с плавающей запятой» (PDF).
  4. ^ Дэвид Х.С. Чен (21 февраля 2017 г.). "Удаление / понижение роли MinNum и MaxNum Операции с IEEE 754 ™ -2018 " (PDF). Получено 6 мая 2019.
  5. ^ "754R Минуты". 19 мая 2017. Получено 25 июн 2017.
  6. ^ Дэвид Голдберг. «Что должен знать каждый компьютерный ученый о числах с плавающей точкой».
  7. ^ "Руководство разработчика программного обеспечения для архитектур Intel 64 и IA-32, том 1: Базовая архитектура". Апрель 2008. С. 118–125, 266–267, 334–335.
  8. ^ «Обоснование международного стандарта - языки программирования - C, редакция 5.10» (PDF). Апрель 2003. с. 180.
  9. ^ «ArithmeticException (Java Platform SE 8)». docs.oracle.com.
  10. ^ "Math :: BigInt". perldoc.perl.org. Получено 12 июн 2015.
  11. ^ "Re: (долго) sNaNs не то, чем они могли бы быть ..." grouper.ieee.org. 15 октября 2010 г.. Получено 5 ноября 2020.
  12. ^ «Архитектура MIPS® для программистов - Том I-A: Введение в архитектуру MIPS64®» (PDF). MIPS Technologies, Inc. 20 ноября 2013 г. с. 79. Получено 27 сентября 2017.

внешние ссылки