Вопрос по c – Является ли хорошей идеей использовать NaN IEEE754 с плавающей точкой для значений, которые не установлены?
=========================================================================================================================

Является ли хорошей идеей использовать NaN (не число) IEEE754 для значений, которые не определены по нематематическим причинам?

В нашем случае они еще не установлены, поскольку значения не были получены от какого-либо другого устройства. Контекст является встроенной системой, использующей значения IEC1131 REAL32.**Edit:** Язык программирования - C, поэтому мы, скорее всего, будем использовать NAN и isnanf (x) из C99. Хотя нам, возможно, понадобятся некоторые дополнительные искажения, чтобы включить их в наш уровень совместимости с ОС.

По умолчанию в языках программирования инициализируются переменные с плавающей запятой положительным нулем, внутренним представлением которого являются все нули. Это не для нас, потому что 0 находится в диапазоне допустимых значений.

Это похоже на чистое решение использовать NaN, но, может быть, это более хлопотно, чем стоит, и мы должны выбрать какое-то другое значение?

Использование NaN в качестве значения по умолчанию является разумным.

Обратите внимание, что некоторые выражения, такие как (0.0 / 0.0), возвращают NaN.



Я использовал NaN в аналогичных ситуациях только из-за этого: обычное значение инициализации по умолчанию 0 также является допустимым значением. До сих пор NaNs работают нормально.

Кстати, хороший вопрос, почему значение инициализации по умолчанию обычно (например, в примитивных типах Java) 0, а не NaN. Не может ли это быть 42 или что-то еще? Интересно, каково обоснование нулей?



Это звучит как хорошее применение для нанс для меня. Хотел бы я подумать об этом ...

Конечно, они должны распространяться как вирус, вот в чем дело.

Я думаю, что я бы использовал Nan вместо одной из бесконечностей. Возможно, было бы неплохо использовать сигнальный нан и заставить его вызывать событие при первом использовании, но к тому времени уже слишком поздно, чтобы при первом использовании было тихо.



Если ваша основная потребность состоит в том, чтобы иметь значение с плавающей запятой, которое не представляет какое-либо число, которое могло бы быть получено от устройства,*and* если устройство гарантирует, что оно никогда не вернет NaN, то мне это кажется разумным.

Просто помните, что в зависимости от вашей среды вам, вероятно, понадобится особый способ обнаружения NaN (не используйте просто`if (x == float.NaN)` или каков твой эквивалент.)



Просто заметил этот вопрос.

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

Тем не менее, есть несколько подводных камней, которые находятся вне контроля комитета 754: как отмечали другие, не все аппаратные средства поддерживают значения NaN на скорости, что может привести к снижению производительности. К счастью, редко приходится выполнять много операций с инициализированными данными в условиях, критичных к производительности.



Будьте осторожны с NaN'ами ... они могут распространяться как лесной пожар, если вы не будете осторожны.

Они являются совершенно допустимым значением для чисел с плавающей запятой, но любые присваивающие их назначения также будут равны NaN, поэтому они распространяются через ваш код. Это очень хорошо в качестве инструмента отладки, если вы его поймаете, однако это также может быть настоящим неудобством, если вы приносите что-то, чтобы выпустить, и где-то есть крайний случай.

D использует это в качестве обоснования для предоставления чисел NaN по умолчанию. (С которым я не уверен, что согласен.)



Я думаю, что это плохая идея в целом. Следует иметь в виду, что большинство процессоров обрабатывают Nan гораздо медленнее, чем «обычные». плавать. И трудно гарантировать, что у вас никогда не будет Nan в обычных условиях. Мой опыт работы с цифровыми вычислениями заключается в том, что они часто приносят больше проблем, чем они того стоят.

Правильное решение состоит в том, чтобы избежать кодирования «отсутствия значения» в поплавке, но сигнализировать об этом по-другому. Это не всегда практично, в зависимости от вашей кодовой базы.



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

* `if (result == DEFAULT_VALUE)`, won't work as expected if `DEFAULT_VALUE` is NaN, as Jon mentioned.
* They can also cause problems with range checking if you're not careful. Consider the function:

```
bool isOutsideRange(double x, double minValue, double maxValue)
{
    return x < minValue || x > maxValue;
}

```

Если x равен NaN, эта функция неправильно сообщит, что x находится между minValue и maxValue.

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

[Изменить: мне изначально удалось набрать «любые сравнения с ними будут правдой» выше, что я не имел в виду, и это неправильно, все они ложные, кроме NaN! = NaN, что верно]



Я чувствую, что это немного смешно, но, по крайней мере, любые другие числа, которые вы выполняете с этим значением NaN, дают NaN как результат - когда вы видите NaN в отчете об ошибке, по крайней мере вы знаете, какую ошибку вы преследуете.