Is !NaN not a NaN?

Is !NaN not a NaN?

本文关键字:NaN not Is      更新时间:2023-10-16

我遇到了这段代码,它发出了一条警告,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评估什么。我们在if中使用f值,所以我们不希望NaN通过检查。

请参阅 https://en.cppreference.com/w/cpp/language/implicit_conversion

可以将整型、浮点型、无作用域枚举、指针和指向成员的指针类型的 prvalue 转换为 bool 类型的 prvalue。

值零(对于整型枚举、浮点枚举和无作用域枚举(以及空指针和空指针指向成员的值变为 false。所有其他值都变为真

因此,!f == 0.0等同于!(f != 0.0) == 0.0(f == 0.0) == falsef != 0.0

如果你想避免if内部出现NaN,你可以使用函数

bool isnan( float arg );

以执行检查。

从函数的引用:

NaN 值从不等于自身或其他 NaN 值。IEEE-754 不需要复制 NaN 来保留其位表示形式(符号和有效负载(,尽管大多数实现都这样做。

测试浮点值是否为 NaN 的另一种方法是将其与自身进行比较:

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

C++草案(N4713(规定:

8.5.2.1 一元运算符 [expr.unary.op]
...
9. 逻辑否定运算符!的操作数在上下文中转换为 bool(条款 7(;如果转换后的操作数false,则其值true,否则false结果的类型为布尔值

7.14 布尔转换 [conv.bool]
1.算术、无作用域枚举、指针或指向成员的指针类型的 prvalue 可以转换为 bool 类型的 prvalue。零值、空指针值或空成员指针值将转换为 false;任何其他值都将转换为 true。

结论:由于 NaN 在表达式!NaN中被上下文转换为true!NaNfalse的,因此不是 NaN

只需使用

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