Что такое nan в математике
NaN все еще может немного удивить
Сначала, я подумал, что это очередной вопрос из тех, которые могут задаваться на собеседовании. Наверное, если как следует пораскинуть мозгами, то можно догадаться до того, каким будет результат. Откинувшись на спинку кресла, начал размышлять, включать логику, вспоминать что-нибудь, на что можно опереться в рассуждениях. Но тщетно! Вдруг стало совершенно очевидно, что найти ответ не удается. Но почему? В чем нужно разбираться, чтобы он был найден? В математике? В языке программирования?
Ответ должен быть NaN. Но почему я не уверен в этом? Всю дорогу была уверенность в том, что любые выражения, содержащие NaN, вернут NaN. Ну разве что только если поделить NaN на ноль — в этом случае будет вызвано исключение ZeroDivisionError. Сто процентов NaN!
Ввожу выражение в ячейку блокнота:
В самом деле? Постойте:
То есть, по какой-то причине, единица в степени NaN — это единица, а вот ноль и все остальные числа в степени NaN — это NaN. Где логика? В чем дело?
Так, давайте еще раз:
Может быть я просто из-за отсутствия какой-то практической надобности в глубоких познаниях о NaN, просто о чем-то не подозревал? А может я знал, но забыл? А может еще хуже — я не знал и забыл?
Заходим на Википедию. Там данный вопрос тоже обозначен как проблема, но почему все именно так устроено, никак не объясняется. Зато узнал что:
Хотя, в то же время:
Что, согласитесь, тоже немного странно.
Ладно, с Википедии отправляемся в C99 на 182 страницу и наконец-то получаем логическое объяснение, почему pow(x, 0) возвращает 1 для любых x, даже для x равного NaN:
Если функция возводится в степень
и при этом
стремится к 0, то в результате получится 1, вне зависимости от того, какое значение имеет
.
А если результат не зависит от числового значения функции , то 1 — является подходящим результатом, даже для NaN. Однако это по-прежнему не объясняет, почему 1 в степени NaN равна 1.
Отыскиваем еще один C99 и на 461 странице не видим никаких объяснений, просто требование того, что pow(+1, y) должно возвращать 1 для всех y, даже равных NaN. Все.
С другой стороны, объяснение, почему pow(NaN, 0)=1 является более предпочтительным, чем pow(NaN, 0)=NaN все-таки наталкивает на мысль о том, что NaN не стоит воспринимать буквально, как Not-a-Number. Допустим, в результате каких- то вычислений мы получили число, превышающее размер памяти, выделенный под данный тип чисел, например:
В результате мы получили inf, что именно это за число мы не знаем, но все же это какое-то число. Затем мы снова что-то вычислили и снова получили слишком большое число:
Разность a и b вернет NaN:
Единственная причина, по которой мы можем считать c не числом, заключается в том, что мы использовали недостаточно точные вычисления. Однако, в c под NaN все же скрывается какое-то значение. О том, что это за значение, мы не знаем. Но все же это число, а раз это число, то нет ничего удивительного в том, что pow(1, NaN)=1.
Почему же тогда pow(0, NaN)=NaN? Дело в том, что если возвести 0 в любую степень, то мы действительно получим ноль. Кроме одного единственного случая — когда степень равна 0:
Из-за чего в выражении pow(0, NaN) появляется неопределенность с конкретным значением NaN. Конечно, вероятность того, что под NaN может скрываться 0 — исчезающе мала и можно было бы принять, что pow(0, NaN)=0. Но все же лучше перестраховаться, мало ли к чему это может привести. Возможно, так и рассуждали, когда создавались стандарты.
Даже не знаю, что еще сказать… если вы заранее знали ответ, то скорее всего вам можно позавидовать, ведь сферы, где могут пригодиться такие познания, наверняка, переполнены интересными задачами. А может и наоборот. Напишите об этом в комментариях.
P.S. Поскольку NaN относится к числам с плавающей точкой, оно может быть ключом словаря:
Имеет ли смысл использовать такое на практике? Думаю, что лучше не стоит.
Что такое nan в математике
СОДЕРЖАНИЕ
Плавающая точка [ править ]
IEEE 754 NaN кодируются с полем экспоненты, заполненным единицами (например, значениями бесконечности), и некоторым ненулевым числом в поле значимости (чтобы сделать их отличными от значений бесконечности); это позволяет определять несколько различных значений NaN, в зависимости от того, какие биты установлены в значимом поле, а также от значения бита ведущего знака (но приложения не обязаны предоставлять четкую семантику для этих отдельных значений NaN).
Например, побитовое значение NaN IEEE 754 одинарной точности (32 бита) будет
s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
Операции с плавающей точкой, отличные от упорядоченных сравнений, обычно передают тихий NaN ( qNaN ). Большинство операций с плавающей запятой в сигнальном NaN ( sNaN ) сигнализируют об исключительной ситуации недопустимой операции; тогда действие исключения по умолчанию такое же, как для операндов qNaN, и они производят qNaN, если производят результат с плавающей запятой.
Сравнение с NaN [ править ]
Сравнение с NaN всегда возвращает неупорядоченный результат даже при сравнении с самим собой. Предикаты сравнения либо сигнализируют, либо не сигнализируют о тихих операндах NaN; версии сигнализации сигнализируют об исключительной ситуации недопустимой операции для таких сравнений. Предикаты равенства и неравенства не сигнализируют, поэтому x = x, возвращающий false, можно использовать для проверки, является ли x тихим NaN. Все другие стандартные предикаты сравнения сигнализируют о получении операнда NaN. Стандарт также предоставляет несигнальные версии этих других предикатов. Предикат определяет, является ли значение NaN, и никогда не сигнализирует об исключении, даже если x является сигнальным NaN. isNaN(x)
Сравнение | NaN ≥ x | NaN ≤ x | NaN> x | NaNОперации создания NaN [ править ]Есть три типа операций, которые могут возвращать NaN: [6] NaN не обязательно генерируются во всех вышеупомянутых случаях. Если операция может вызвать исключительную ситуацию и ловушки не замаскированы, тогда операция вызовет ловушку. [7] Если операнд является тихим NaN, а также нет сигнального операнда NaN, то нет условия исключения и результатом является тихий NaN. Явное присвоение не вызовет исключения даже для сигнализации NaN. Тихий NaN [ править ]Тихие NaN, или qNaN, не вызывают никаких дополнительных исключений, поскольку они распространяются через большинство операций. Исключение составляют случаи, когда NaN нельзя просто передать в неизмененном виде в вывод, например, при преобразовании формата или некоторых операциях сравнения. Сигнализация NaN [ править ]При обнаружении обработчик прерывания может декодировать sNaN и вернуть индекс вычисленному результату. На практике такой подход сталкивается со многими сложностями. Обработка знакового бита NaN для некоторых простых операций (таких как абсолютное значение ) отличается от обработки для арифметических операций. Стандарт не требует ловушек. Есть и другие подходы к решению такого рода проблем, которые были бы более переносимыми. Определение функции [ править ]Существуют разногласия по поводу правильного определения результата числовой функции, которая получает в качестве входных данных тихий NaN. Одна точка зрения состоит в том, что NaN должно распространяться на выход функции во всех случаях, чтобы распространять индикацию ошибки. Другой взгляд, принятый стандартами ISO C99 и IEEE 754-2008 в целом, заключается в том, что если функция имеет несколько аргументов и вывод однозначно определяется всеми входами, отличными от NaN (включая бесконечность), тогда это значение должно быть результатом. Так, например, значение, возвращаемое функцией hypot(±∞, qNaN) и, hypot(qNaN, ±∞) равно + ∞. Целое число NaN [ править ]Показать [ править ]Различные операционные системы и языки программирования могут иметь разные строковые представления NaN. Поскольку на практике закодированные NaN имеют знак, бит молчания / сигнализации и необязательную «диагностическую информацию» (иногда называемую полезной нагрузкой ), они также часто встречаются в строковых представлениях NaN, например: (существуют другие варианты). Кодировка [ править ]Первый вариант был предпочтительнее, поскольку он позволяет реализации заглушить сигнальный NaN, просто установив бит сигнализации / молчания в 1. Обратное невозможно с последним выбором, поскольку установка бита сигнализации / молчания в 0 может дать бесконечность. [11] Версия стандарта IEEE 754 ( IEEE 754-2008 ) 2008 г. дает формальные рекомендации по кодированию состояния сигнализации / молчания. Для соответствия IEEE 754-2008 значение бита сигнализации / молчания в последних процессорах MIPS теперь настраивается через поле NAN2008 регистра FCSR. Эта поддержка является необязательной в MIPS Release 3 и требуется в Release 5. [12] Состояние / значение остальных битов значения поля не определены стандартом. Это значение называется «полезной нагрузкой» NaN. Если операция имеет один вход NaN и передает его на выход, полезная нагрузка результата NaN должна быть полезной нагрузкой входного NaN (это не всегда возможно для двоичных форматов, когда состояние сигнализации / молчания кодируется is_signaling флагом, как объяснено выше. ). Если имеется несколько входов NaN, полезная нагрузка результата NaN должна быть из одного из входных NaN; в стандарте не указано, какие именно. СОДЕРЖАНИЕПлавающая запятаяIEEE 754 NaN кодируются с полем экспоненты, заполненным единицами (например, значениями бесконечности), и некоторым ненулевым числом в поле значимости (чтобы сделать их отличными от значений бесконечности); это позволяет определять несколько различных значений NaN, в зависимости от того, какие биты установлены в значимом поле, а также от значения бита ведущего знака (но приложения не обязаны предоставлять четкую семантику для этих отдельных значений NaN). Например, побитовое значение NaN одинарной точности IEEE 754 (32 бита) будет Операции с плавающей точкой, отличные от упорядоченных сравнений, обычно передают тихий NaN ( qNaN ). Большинство операций с плавающей запятой в сигнальном NaN ( sNaN ) сигнализируют об исключительной ситуации недопустимой операции; тогда действие исключения по умолчанию такое же, как для операндов qNaN, и они производят qNaN, если производят результат с плавающей запятой. Сравнение с NaNСравнение с NaN всегда возвращает неупорядоченный результат даже при сравнении с самим собой. Предикаты сравнения либо сигнализируют, либо не сигнализируют о тихих операндах NaN; версии сигнализации сигнализируют об исключительной ситуации недопустимой операции для таких сравнений. Предикаты равенства и неравенства не сигнализируют, поэтому x = x, возвращающий false, можно использовать для проверки, является ли x тихим NaN. Все другие стандартные предикаты сравнения сигнализируют о получении операнда NaN. Стандарт также предоставляет несигнальные версии этих других предикатов. Предикат определяет, является ли значение NaN, и никогда не сигнализирует об исключении, даже если x является сигнальным NaN. isNaN(x)
|
---|