Является ли! NaN не NaN? - PullRequest
       38

Является ли! NaN не NaN?

0 голосов
/ 22 октября 2018

Я наткнулся на этот код, который издает предупреждение с gcc:

float f;
// Calculate a value for f
if (!f == 0.0)
{
    // Handle it being non-zero
}

Вероятно, это была просто опечатка другого члена команды, и проверка кода на самом деле означала:

if (f != 0.0)
// OR
if (!(f == 0.0))

Я исправил код, но мне было просто интересно, что оценит !NaN.Мы используем значение f внутри if, поэтому мы не хотим, чтобы NaN s проходил проверку.

Ответы [ 3 ]

0 голосов
/ 22 октября 2018

Просто используйте

if (!isnan(f)&& !f == 0.0)
    {
        cout<<"Filtered NaN values"<<endl;

    }
0 голосов
/ 22 октября 2018

См. https://en.cppreference.com/w/cpp/language/implicit_conversion

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

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

Поэтому !f == 0.0 эквивалентно !(f != 0.0) == 0.0 или (f == 0.0) == false или f != 0.0

0 голосов
/ 22 октября 2018

Если вы хотите избежать NaN внутри if, вы можете использовать функцию

bool isnan( float arg );

для выполнения проверки.

Из ссылка функции:

Значения NaN никогда не сравниваются ни с самими собой, ни с другими значениями NaN. Копирование NaN не требуется, согласно IEEE-754, длясохранить свое битовое представление (знак и полезную нагрузку), хотя большинство реализаций делают.

Другой способ проверить, является ли значение с плавающей точкой NaN, - сравнить его с самим собой:

bool is_nan(double x) { return x != x; } 

Черновик C ++ (N4713) гласит:

8.5.2.1 Унарные операторы [expr.unary.op]
...
9. Операнд оператора логического отрицания ! контекстно преобразуется вbool (пункт 7);его значение равно true, если преобразованный операнд равен false и false в противном случае. Тип результата: bool .

7.14 Булевы преобразования [conv.bool]
1. Значение арифметического, перечисления с незаданной областью, указателя илиТип указатель на член может быть преобразован в тип значения bool.Нулевое значение, нулевое значение указателя или нулевое значение указателя члена преобразуется в ложь; любое другое значение преобразуется в true.

Вывод: Поскольку NaN контекстуально преобразуется как true в выражении !NaN, !NaNравен false и, следовательно, не является NaN .

...