Float или Double Special Value - PullRequest
       7

Float или Double Special Value

5 голосов
/ 02 декабря 2008

У меня есть двойные (или плавающие) переменные, которые могут быть «пустыми», так как в них нет действительного значения. Как я могу представить это условие с помощью встроенных типов float и double?

Одним из вариантов может быть оболочка с плавающей точкой и логическим значением, но она не может работать, поскольку в моих библиотеках есть контейнеры, в которых хранятся двойники, а не объекты, которые ведут себя как двойники. Другой будет использовать NaN (std :: numeric_limits). Но я не вижу способа проверить, является ли переменная NaN.

Как я могу решить проблему с необходимостью "специального" значения с плавающей запятой, чтобы обозначать что-то отличное от числа?

Ответы [ 4 ]

7 голосов
/ 02 декабря 2008

Мы сделали это, используя NaN:

double d = std::numeric_limits<double>::signaling_NaN();
bool isNaN = (d != d);

Значения NaN, сравниваемые на равенство с самим собой, приведут к ложному результату. Таким способом вы проверяете NaN, но, похоже, он действителен только в том случае, если значение std::numeric_limits<double>::is_iec559 равно true (если это так, оно также соответствует ieee754)

В C99 есть макрос под названием isnan для этого в math.h, который проверяет число с плавающей запятой и для значения NaN.

6 голосов
/ 02 декабря 2008

В Visual C ++ есть нестандартная функция _isnan(double), которую можно импортировать с помощью float.h.

В C есть функция isnan(double), которую вы можете импортировать через math.h.

В C ++ есть функция isnan (double), которую вы можете импортировать через cmath.

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

2 голосов
/ 02 декабря 2008

Это не встроенный тип, но я обычно использую boost::optional для такого рода вещей. Если вы абсолютно не можете использовать это, возможно, указатель сделает свое дело - если указатель равен NULL, то вы знаете, что результат не содержит допустимого значения.

1 голос
/ 02 декабря 2008

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

Это позор. В C ++ легко создать шаблонный класс, который автоматически преобразуется в фактический двойной (ссылочный) атрибут. (Или ссылка на любой другой тип по этому вопросу.) Вы просто используете оператор приведения в шаблонном классе. Например: оператор TYPE & () {возвращаемое значение; } Затем вы можете использовать HasValue везде, где обычно используете double.

Другой будет использовать NaN (std :: numeric_limits). Но я не вижу способа проверить, является ли переменная NaN.

Как отметили litb и Джеймс Шек , C99 предоставляет нам isnan ().

Но будьте осторожны с этим! Значения Nan делают математику и логику по-настоящему интересными! Можно подумать, что число не может быть одновременно NOT> = foo и NOT <= foo. Но с NaN это может. </p>

Есть причина, по которой я держу макрос WARN-IF-NAN (X) в своем наборе инструментов. В прошлом у меня возникали интересные проблемы.

...