stringtranslate.com

НЭН

В вычислениях NaN ( / n æ n / ), обозначающий не число , представляет собой конкретное значение числового типа данных (часто число с плавающей запятой ), которое не определено как число, например , результат 0/0. . Систематическое использование NaN было введено стандартом IEEE 754 для чисел с плавающей запятой в 1985 году наряду с представлением других неконечных величин, таких как бесконечности .

В математике результат 0/0 обычно не определяется как число [a] и поэтому может быть представлен в вычислительных системах как NaN.

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

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

Плавающая запятая

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

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

Например, NaN одинарной точности (32 бита) IEEE 754 будет закодирован как

s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx

где s — знак (чаще всего игнорируется в приложениях), а последовательность x представляет собой ненулевое число (нулевое значение кодирует бесконечность). На практике для определения типа NaN используется старший бит из x : «тихий NaN» или «сигнальный NaN» (подробности см. в разделе «Кодирование»). Остальные биты кодируют полезную нагрузку (чаще всего игнорируемую в приложениях).

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

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

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

Сравнение с NaN

Сравнения определены стандартом IEEE 754 , чтобы учитывать возможные операнды NaN. [6] При сравнении двух действительных чисел или расширенных действительных чисел (как в форматах с плавающей запятой IEEE 754) первое число может быть меньше, равно или больше второго числа. Это дает три возможных отношения. Но когда хотя бы один операнд сравнения имеет значение NaN, эта трихотомия не применяется, и необходимо четвертое отношение: unordered . В частности, два значения NaN сравниваются как неупорядоченные, а не как равные.

Как указано, предикаты, связанные с математическими символами <, ≤, =, ≥, > (или эквивалентными обозначениями в языках программирования), возвращают значение false в неупорядоченном отношении. Так, например, NOT ( x < y ) логически не эквивалентен xy : в неупорядоченном виде, т. е. когда x или y имеет значение NaN, первый возвращает true, а второй возвращает false. Однако ≠ определяется как отрицание =, поэтому он возвращает true в неупорядоченном виде.

Из этих правил можно использовать сравнение x с самим собой, xx или x = x , чтобы проверить, является ли x NaN или не-NaN.

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

Стандарт IEEE для чисел с плавающей запятой требует, чтобы NaN ≠ NaN сохранялось. Напротив, частный стандарт позиционной арифметики 2022 года имеет аналогичную концепцию NaR (Not a Real), где выполняется NaR = NaR . [7]

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

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

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

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

Тихий НЭН

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

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

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

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

Операции с полезной нагрузкой

IEEE 754-2019 рекомендует реализовать операции getPayload , setPayload и setPayloadSignaling , [10] стандартизируя доступ к полезным нагрузкам для оптимизации использования приложений. [11] Согласно справочному документу IEEE 754-2019, эту рекомендацию следует интерпретировать как «требующуюся для новых реализаций с оговоркой для обратной совместимости». [12]

Кодирование

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

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

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

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

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

Канонический NaN

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

Использование ограниченного количества представлений NaN позволяет системе использовать другие возможные значения NaN для неарифметических целей, наиболее важным из которых является «NaN-бокс», то есть использование полезных данных для произвольных данных. [23] (Эта концепция «канонического NaN» не совпадает с концепцией «канонического кодирования» в IEEE 754.)

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

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

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

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

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

Целое число NaN

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

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

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

Отображать

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

нан (C, C++, Python)NaN (ECMAScript, Rust, C#, Julia). Джулия может показывать альтернативный NaN, в зависимости от точности, NaN32 и NaN16; NaN предназначен для типа Float64.NaN%НАН (C, C++, Rust)NaNQ (IBM XL и AIX: Fortran, предложение C++ n2290)NaNS (то же самое)qNaNСНАН1.#SNAN (Excel)1.#QNAN (Excel)-1.#IND (Excel)+nan.0 (Схема)

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

Не все языки допускают существование нескольких NaN. Например, ECMAScript повсюду использует только одно значение NaN.

Рекомендации

Примечания

  1. ^ 0/0 не определено как число как в системе действительных чисел , так и в расширенной системе действительных чисел , в то время как 1/±0, например, может быть последовательно присвоено значение ±∞ в последней системе, предполагая нуль со знаком .
  2. ^ IEEE 754-2008 рекомендует, но не требует распространения полезной нагрузки NaN. Большинство процессоров предпочитают следовать этой рекомендации, но сами по себе не генерируют ненулевую полезную нагрузку. [19] Таким образом, поведение RISC-V не рекомендуется, но соответствует требованиям.

Цитаты

  1. ^ аб Боуман, Кеннет (2006). Введение в программирование с помощью IDL: интерактивный язык данных . Академическая пресса. п. 26. ISBN 978-0-12-088559-6.
  2. ^ Пресс, Уильям Х.; Теукольский, Саул А.; Веттерлинг, Уильям Т.; Фланнери, Брайан П. (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. ^ IEEE 754 2019, §5.11
  7. ^ Стандарт для положительной арифметики (2022)
  8. ^ Дэвид Голдберг (1991). «Что должен знать каждый ученый-компьютерщик о числах с плавающей запятой».
  9. ^ «Руководство разработчика программного обеспечения для архитектур Intel 64 и IA-32, том 1: Базовая архитектура» . Апрель 2008 г., стр. 118–125, 266–267, 334–335.
  10. ^ IEEE 754 2019, §9.7
  11. ^ «Справочное обсуждение новых функций полезной нагрузки» .
  12. ^ «Пересмотр стандарта IEEE для арифметики с плавающей запятой должен выйти в 2019 году» (PDF) .
  13. ^ «Re: (длинные) sNaNs не такие, какими могли бы быть...» grouper.ieee.org . 15 октября 2010 года . Проверено 5 ноября 2020 г.
  14. ^ IEEE 754 2019, §3.4
  15. ^ IEEE 754 2019, §6.2.1
  16. ^ IEEE 754 2019, §3.5.2
  17. ^ «Архитектура MIPS для программистов - Том IA: Введение в архитектуру MIPS64» (PDF) . MIPS Technologies, Inc. 20 ноября 2013 г. с. 79 . Проверено 27 сентября 2017 г.
  18. ^ Эмбеддев, Пять. «F» Стандартное расширение для чисел с плавающей запятой одинарной точности, версия 2.2 / Руководство по набору команд RISC-V, том I: ISA уровня пользователя RISC-V». Пять EmbedDev .
  19. ^
    • Туман, Агнер (11 апреля 2018 г.). «Распространение полезных данных NaN — нерешенные проблемы» (PDF) .
    • Фог Агнер (27 апреля 2020 г.). «Отслеживание исключений с плавающей запятой и распространение NAN» (PDF) .
  20. ^ «Обработка NaN и NaN по умолчанию (Справочное руководство по архитектуре ARM, версии ARMv7-A и ARMv7-R)» . Документация — Arm Developer .
  21. ^ ab «Какова мотивация канонизации NaN? · Проблема № 1463 · WebAssembly/design». Гитхаб .- см. ответ Дэна Гохмана «sunfishcode».
  22. ^ «Глава 4. Типы, значения и переменные». docs.oracle.com . По большей части платформа Java SE обрабатывает значения NaN данного типа как свернутые в одно каноническое значение, и, следовательно, эта спецификация обычно относится к произвольному NaN, как к каноническому значению.
  23. Нистром, Роберт (28 июля 2021 г.). «§ 30.3 Упаковка NaN». Создание переводчиков. Женевер Беннинг. ISBN 978-0-9905829-3-9.
  24. ^ «Обоснование международного стандарта — Языки программирования — C, версия 5.10» (PDF) . Апрель 2003. с. 180.
  25. ^ «ArithmeticException (платформа Java SE 8)» . docs.oracle.com .
  26. ^ "Математика::BigInt". perldoc.perl.org . Проверено 12 июня 2015 г.
  27. ^ «Разбор чисел с плавающей запятой (Библиотека GNU C)» . www.gnu.org . Проверено 9 сентября 2021 г. Если указаны символы… , они используются каким-то неопределённым образом для выбора конкретного представления NaN (их может быть несколько).

Стандарты

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