Почему NaN (не число) доступно только для двойников? - PullRequest
41 голосов
/ 12 июня 2009

У меня есть бизнес-класс, который содержит два обнуляемых десятичных свойства. Третье свойство возвращает результат умножения двух других свойств. Если HasValue имеет значение true для двух обнуляемых типов, то я умножаю и возвращаю результат. У меня есть несколько вариантов возвращаемого значения, если одно или оба свойства имеют значение null:

  • Возврат 0
  • Брось исключение
  • Вернуть магическое число (-1)
  • Вернуть десятичную? (РЕДАКТИРОВАТЬ - см. Комментарии)

Я думал, что один из моих вариантов - вернуть NaN, но я вижу, что это возможно только для типа double. Почему это?

Для справки, возвращение 0 имеет наибольшее значение в этом случае, и это то, что я планирую сделать, если у кого-то нет лучшего предложения.

Ответы [ 2 ]

37 голосов
/ 12 июня 2009

Интегральные типы в .NET используют систему представления двух дополнений для представления. Хотя они могли зарезервировать некоторые битовые шаблоны для специальных значений, они решили не делать этого. double и float используют совершенно другую систему представления (IEEE 754), которая резервирует некоторые специальные битовые комбинации для NaN, + Infinity, -Infinity, ...

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

decimal предназначен для использования в "реальных" десятичных числах с плавающей запятой. Расчеты double и float предназначены для вычислений редко. Что бы NaN выразил бы для числа реального мира?

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

РЕДАКТИРОВАТЬ (очень распространенное заблуждение о десятичной дроби):

Как также отмечено в MSDN , decimal не является фиксированной точкой. Это число с плавающей запятой:

Десятичное число - это значение с плавающей запятой, которое состоит из знака, числового значения, где каждая цифра в значении находится в диапазоне от 0 до 9, и масштабного коэффициента, который указывает положение плавающей десятичной запятой, которая отделяет интеграл и дробные части числового значения.

0 голосов
/ 27 октября 2016

Для разрешения NAN и Infinity используйте это

if (Double.IsNaN(YourValue) || Double.IsInfinity(YourValue))
{
    YourValue = 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...