检查 C++ 中的 double(或 float)是否为 NaN;
Is there an isnan() function?
PS.: I'm in MinGW (if that makes a difference).
I had this solved by using isnan() from <math.h>
, which doesn't exist in <cmath>
, which I was #include
ing at first.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(21)
根据 IEEE 标准,NaN 值具有奇怪的属性,涉及它们的比较总是错误。 也就是说,对于浮点数 f,
f != f
仅当 f 为 NaN 时才为 true。请注意,正如下面的一些评论所指出的那样,并非所有编译器在优化代码时都尊重这一点。
对于任何声称使用 IEEE 浮点的编译器,这个技巧应该有效。 但我不能保证它在实践中会发挥作用。 如有疑问,请咨询您的编译器。
According to the IEEE standard, NaN values have the odd property that comparisons involving them are always false. That is, for a float f,
f != f
will be true only if f is NaN.Note that, as some comments below have pointed out, not all compilers respect this when optimizing code.
For any compiler which claims to use IEEE floating point, this trick should work. But I can't guarantee that it will work in practice. Check with your compiler, if in doubt.
方案:如果您使用的是 C++11
自从提出这个问题以来,出现了一些新的进展:重要的是要知道
std::isnan()
是 C++11 的一部分第一个解决
在标头
中定义确定给定浮点数 arg 是否不是数字 (
NaN
)。参数
arg
:浮点值返回值
true
if arg isNaN
, < code>false 否则参考
http:// /en.cppreference.com/w/cpp/numeric/math/isnan
请注意,如果您使用 g++,这与 -fast-math 不兼容,请参阅下面的其他建议。
其他解决方案:如果您使用不符合 C++11 的工具
对于 C99,在 C 中,这是作为返回 int 值的宏
isnan(c)
实现的。x
的类型应为 float、double 或 long double。不同的供应商可能包含也可能不包含函数
isnan()
。检查
NaN
的据称可移植方法是使用 IEEE 754 属性,即NaN
不等于其自身:即x == x
将如果x
为NaN
,则为 false。然而,最后一个选项可能不适用于每个编译器和某些设置(特别是优化设置),因此在最后的手段中,您始终可以检查位模式...
First solution: if you are using C++11
Since this was asked there were a bit of new developments: it is important to know that
std::isnan()
is part of C++11Synopsis
Defined in header
<cmath>
Determines if the given floating point number arg is not-a-number (
NaN
).Parameters
arg
: floating point valueReturn value
true
if arg isNaN
,false
otherwiseReference
http://en.cppreference.com/w/cpp/numeric/math/isnan
Please note that this is incompatible with -fast-math if you use g++, see below for other suggestions.
Other solutions: if you using non C++11 compliant tools
For C99, in C, this is implemented as a macro
isnan(c)
that returns an int value. The type ofx
shall be float, double or long double.Various vendors may or may not include or not a function
isnan()
.The supposedly portable way to check for
NaN
is to use the IEEE 754 property thatNaN
is not equal to itself: i.e.x == x
will be false forx
beingNaN
.However the last option may not work with every compiler and some settings (particularly optimisation settings), so in last resort, you can always check the bit pattern ...
当前 C++ 标准库中没有可用的
isnan()
函数。 它是在 C99 中引入的,并定义为 宏不是函数。 C99 定义的标准库元素不是当前 C++ 标准 ISO/IEC 14882:1998 的一部分,也不是其更新版 ISO/IEC 14882:2003 的一部分。2005年提出技术报告1。 TR1 为 C++ 带来了与 C99 的兼容性。 尽管事实上它从未被正式采用成为 C++ 标准,但许多 (GCC 4.0+ 或 Visual C++ 9.0+ C++ 实现确实提供 TR1 功能,全部或仅部分(Visual C++ 9.0 不提供 C99 数学函数),
如果 TR1 可用,则
cmath
包括 C99 元素,例如isnan()
、。 >isfinite()
等,但它们被定义为函数,而不是宏,通常在std::tr1::
命名空间中,尽管有许多实现(即 Linux 上的 GCC 4+ 或Mac OS X 10.5+ 上的 XCode)将它们直接注入到std::
中,因此std::isnan
定义良好,此外,C++ 的某些实现仍然使 C99
有效。 >isnan()
宏可用于 C++(通过cmath
或math.h
包含),这可能会导致更多混乱,开发人员可能会认为这是标准行为。关于 Viusal C++ 的说明,如上所述,它不提供
std::isnan
也不提供std::tr1::isnan
,但它提供了一个定义为std::isnan
的扩展函数code>_isnan() 自 Visual C++ 6.0在 XCode 上,还有更多乐趣。 如前所述,GCC 4+ 定义了
std::isnan
。 对于旧版本的编译器和库形式的 XCode,似乎(这里是 相关讨论),还没有机会检查自己)定义了两个函数,Intel上的__inline_isnand()
和Power PC上的__isnand()
。There is no
isnan()
function available in current C++ Standard Library. It was introduced in C99 and defined as a macro not a function. Elements of standard library defined by C99 are not part of current C++ standard ISO/IEC 14882:1998 neither its update ISO/IEC 14882:2003.In 2005 Technical Report 1 was proposed. The TR1 brings compatibility with C99 to C++. In spite of the fact it has never been officially adopted to become C++ standard, many (GCC 4.0+ or Visual C++ 9.0+ C++ implementations do provide TR1 features, all of them or only some (Visual C++ 9.0 does not provide C99 math functions).
If TR1 is available, then
cmath
includes C99 elements likeisnan()
,isfinite()
, etc. but they are defined as functions, not macros, usually instd::tr1::
namespace, though many implementations (i.e. GCC 4+ on Linux or in XCode on Mac OS X 10.5+) inject them directly tostd::
, sostd::isnan
is well defined.Moreover, some implementations of C++ still make C99
isnan()
macro available for C++ (included throughcmath
ormath.h
), what may cause more confusions and developers may assume it's a standard behaviour.A note about Viusal C++, as mentioned above, it does not provide
std::isnan
neitherstd::tr1::isnan
, but it provides an extension function defined as_isnan()
which has been available since Visual C++ 6.0On XCode, there is even more fun. As mentioned, GCC 4+ defines
std::isnan
. For older versions of compiler and library form XCode, it seems (here is relevant discussion), haven't had chance to check myself) two functions are defined,__inline_isnand()
on Intel and__isnand()
on Power PC.还有一个 标题-Boost 中唯一的库 提供了处理浮点数据类型的简洁工具。
您将获得以下功能:
如果您有时间,请查看 Boost 的整个数学工具包,它有许多有用的工具,并且正在快速增长。
此外,在处理浮点和非浮点时,查看 数字转换。
There is also a header-only library present in Boost that have neat tools to deal with floating point datatypes
You get the following functions:
If you have time then have a look at whole Math toolkit from Boost, it has many useful tools and is growing quickly.
Also when dealing with floating and non-floating points it might be a good idea to look at the Numeric Conversions.
共有三种“官方”方式:posix
isnan
宏、c++0xisnan
函数模板、或 Visual c++_isnan
函数。不幸的是,检测使用哪一个是相当不切实际的。
不幸的是,没有可靠的方法来检测您是否具有 NaN 的 IEEE 754 表示形式。 标准库提供了官方的这种方式(
numeric_limits::is_iec559
)。 但实际上,诸如 g++ 之类的编译器却搞砸了。理论上,可以简单地使用
x != x
,但 g++ 和 Visual C++ 等编译器却把它搞砸了。因此,最后,测试特定的 NaN 位模式,假设(并希望在某个时候强制执行!)特定的表示形式,例如 IEEE 754。
编辑:作为示例对于“诸如 g++ 之类的编译器……搞砸了”,请考虑
使用 g++ (TDM-2 mingw32) 4.4.1 进行编译:
There are three "official" ways: posix
isnan
macro, c++0xisnan
function template, or visual c++_isnan
function.Unfortunately it's rather impractical to detect which of those to use.
And unfortunately, there's no reliable way to detect whether you have IEEE 754 representation with NaNs. The standard library offers an official such way (
numeric_limits<double>::is_iec559
). But in practice compilers such as g++ screw that up.In theory one could use simply
x != x
, but compilers such as g++ and visual c++ screw that up.So in the end, test for the specific NaN bitpatterns, assuming (and hopefully enforcing, at some point!) a particular representation such as IEEE 754.
EDIT: as an example of "compilers such as g++ … screw that up", consider
Compiling with g++ (TDM-2 mingw32) 4.4.1:
如果编译器支持 c99 扩展,则有一个 std::isnan ,但我不确定 mingw 是否支持。
这是一个小函数,如果您的编译器没有标准函数,它应该可以工作:
There is an std::isnan if you compiler supports c99 extensions, but I'm not sure if mingw does.
Here is a small function which should work if your compiler doesn't have the standard function:
您可以使用
limits
标准库中定义的numeric_limits::quiet_NaN( )
进行测试。 为 double 定义了一个单独的常量。我不知道这是否适用于所有平台,因为我只在 Linux 上使用 g++ 进行了测试。
You can use
numeric_limits<float>::quiet_NaN( )
defined in thelimits
standard library to test with. There's a separate constant defined fordouble
.I don't know if this works on all platforms, as I only tested with g++ on Linux.
您可以使用
isnan()
函数,但需要包含 C 数学库。由于此功能是 C99 的一部分,因此并非在所有地方都可用。 如果您的供应商不提供该功能,您还可以定义自己的变体以实现兼容性。
You can use the
isnan()
function, but you need to include the C math library.As this function is part of C99, it is not available everywhere. If your vendor does not supply the function, you can also define your own variant for compatibility.
从 C++14 开始,有多种方法可以测试浮点数
值
是否为 NaN。在这些方法中,仅检查数字表示的位,
正如我原来的答案中所述,工作可靠。 特别是,
std::isnan
和经常建议的检查v != v
,不能可靠地工作,不应该使用,以免当有人决定时你的代码停止正常工作需要浮点优化,并要求编译器这样做。 这种情况可以改变,编译器可以变得更加一致,但对于这个问题来说,自原始答案以来的 6 年里还没有发生过。大约六年来,我最初的答案是这个问题的选定解决方案,这是可以的。 但最近选择了一个高度赞成的答案,建议使用不可靠的
v != v
测试。 因此,有了这个额外的更新答案(我们现在有了 C++11 和 C++14 标准,以及即将推出的 C++17)。从 C++14 开始,检查 NaN 的主要方法是:
std::isnan(value) )
是自 C++11 以来预期的标准库方式。
isnan
显然与Posix 宏同名,但在实践中这不是问题。 主要问题是
当请求浮点算术优化时,至少使用一个主编译器,即 g++,
std::isnan
对于 NaN 参数返回false
.(fpclassify(value) == FP_NAN) )
与
std::isnan
遇到同样的问题,即不可靠。(值!=值))
在许多 SO 答案中推荐。 遇到与 std::isnan 相同的问题,即
不可靠。
(值 == Fp_info::quiet_NaN()) )
这是一个使用标准行为不应检测 NaN 的测试,但使用
优化的行为也许可以检测 NaN(由于优化的代码只是比较
直接位级表示),也许与另一种方式结合
覆盖标准的未优化行为,可以可靠地检测 NaN。 很遗憾
事实证明它无法可靠地工作。
(ilogb(值) == FP_ILOGBNAN) )
与
std::isnan
遇到同样的问题,即不可靠。isunordered(1.2345,值))
与
std::isnan
遇到同样的问题,即不可靠。is_ieee754_nan(值))
这不是标准功能。 它根据 IEEE 754 检查位
标准。 它完全可靠但是代码在某种程度上依赖于系统。
在下面的完整测试代码中,“成功”是指表达式是否报告值的 Nan-ness。 对于大多数表达式来说,这种成功衡量标准(检测 NaN 且仅检测 NaN 的目标)与其标准语义相对应。 然而,对于
(value == Fp_info::quiet_NaN()) )
表达式,标准行为是它不能用作 NaN 检测器。g++ 的结果(再次注意
(value == Fp_info::quiet_NaN())
的标准行为是它不能作为 NaN 检测器工作,它在这里非常具有实际意义):Visual C++ 的结果:
总结以上结果,仅直接测试位级表示,使用此测试程序中定义的 is_ieee754_nan 函数,在 g++ 和 Visual 的所有情况下都能可靠地工作C++。
附录:
发布上述内容后,我意识到还有另一种可能测试 NaN 的方法,在 这里是另一个答案,即
((value < 0) == (value >= 0))
。 事实证明,这对于 Visual C++ 来说工作得很好,但对于 g++ 的-ffast-math
选项却失败了。 只有直接的位模式测试才能可靠地工作。As of C++14 there are a number of ways to test if a floating point number
value
is a NaN.Of these ways, only checking of the bits of the number's representation,
works reliably, as noted in my original answer. In particular,
std::isnan
and the often proposed checkv != v
, do not work reliably and should not be used, lest your code stops working correctly when someone decides that floating point optimization is needed, and asks the compiler to do that. This situation can change, compilers can get more conforming, but for this issue that hasn't happened in the 6 years since the original answer.For about 6 years my original answer was the selected solution for this question, which was OK. But recently a highly upvoted answer recommending the unreliable
v != v
test has been selected. Hence this additional more up-to-date answer (we now have the C++11 and C++14 standards, and C++17 on the horizon).The main ways to check for NaN-ness, as of C++14, are:
std::isnan(value) )
is the intended standard library way since C++11.
isnan
apparently conflicts with thePosix macro of the same name, but in practice that isn't a problem. The main problem is
that when floating point arithmetic optimization is requested, then with at least one main compiler, namely g++,
std::isnan
returnsfalse
for NaN argument.(fpclassify(value) == FP_NAN) )
Suffers from the same problem as
std::isnan
, i.e., is not reliable.(value != value) )
Recommended in many SO answers. Suffers from the same problem as
std::isnan
, i.e.,is not reliable.
(value == Fp_info::quiet_NaN()) )
This is a test that with standard behavior should not detect NaNs, but that with the
optimized behavior maybe could detect NaNs (due to optimized code just comparing the
bitlevel representations directly), and perhaps combined with another way to
cover the standard un-optimized behavior, could reliably detect NaN. Unfortunately
it turned out to not work reliably.
(ilogb(value) == FP_ILOGBNAN) )
Suffers from the same problem as
std::isnan
, i.e., is not reliable.isunordered(1.2345, value) )
Suffers from the same problem as
std::isnan
, i.e., is not reliable.is_ieee754_nan( value ) )
This isn't a standard function. It's checking of the bits according to the IEEE 754
standard. It's completely reliable but the code is somewhat system-dependent.
In the following complete test code “success” is whether an expression reports Nan-ness of the value. For most expressions this measure of success, the goal of detecting NaNs and only NaNs, corresponds to their standard semantics. For the
(value == Fp_info::quiet_NaN()) )
expression, however, the standard behavior is that it doesn't work as a NaN-detector.Results with g++ (note again that the standard behavior of
(value == Fp_info::quiet_NaN())
is that it doesn't work as a NaN-detector, it's just very much of practical interest here):Results with Visual C++:
Summing up the above results, only direct testing of the bit-level representation, using the
is_ieee754_nan
function defined in this test program, worked reliably in all cases with both g++ and Visual C++.Addendum:
After posting the above I became aware of yet another possible to test for NaN, mentioned in another answer here, namely
((value < 0) == (value >= 0))
. That turned out to work fine with Visual C++ but failed with g++'s-ffast-math
option. Only direct bitpattern testing works reliably.以下代码使用 NAN 的定义(所有指数位集,至少一个小数位集),并假设 sizeof(int) = sizeof(float) = 4。您可以在 Wikipedia 中查找 NAN 了解详细信息。
bool IsNan(浮点值)
{
返回 ((*(UINT*)&值) & 0x7fffffff) > 0x7f800000;
}
The following code uses the definition of NAN (all exponent bits set, at least one fractional bit set) and assumes that sizeof(int) = sizeof(float) = 4. You can look up NAN in Wikipedia for the details.
bool IsNan( float value )
{
return ((*(UINT*)&value) & 0x7fffffff) > 0x7f800000;
}
nan 预防
我对这个问题的回答是不要对
nan
使用追溯检查。 对0.0/0.0
形式的分区使用预防性检查。nan
由操作0.f/0.f
或0.0/0.0
产生。nan
是代码稳定性的可怕克星,必须非常小心地检测和预防它1。nan
与普通数字不同的属性:nan
有毒,(5*nan
=nan
)nan
不等于任何东西,甚至不等于它本身 (nan
!=nan
)nan
不大于任何东西 (nan
!> 0)nan
不小于任何值 (nan
!< 0)列出的最后 2 个属性是反逻辑的并且将导致依赖于与
nan
数字比较的代码出现奇怪的行为(最后第三个属性也很奇怪,但您可能永远不会看到x != x ? 在你的代码中(除非你正在检查 nan (不可靠)))。
在我自己的代码中,我注意到 nan 值往往会产生难以发现的错误。 (请注意
inf
或-inf
的情况不是。(-inf
< 0) 返回TRUE
,( 0inf
) 返回 TRUE,甚至 (-inf
<inf
) 返回 TRUE因此,根据我的经验,代码的行为通常仍然符合预期)。在 nan 下做什么
你想在
0.0/0.0
下发生什么 必须作为特殊情况处理,但你做什么必须取决于你期望得到的数字的代码。在上面的示例中,(
0.f/FLT_MIN
) 的结果基本上将为0
。 您可能希望使用0.0/0.0
来生成HUGE
。 所以,在上面,如果 x 是
0.f
,则会产生inf
(实际上具有如上所述的相当好的/非破坏性行为)。请记住,整数除以 0导致运行时异常。 因此,您必须始终检查整数是否被 0 除。仅仅因为
0.0/0.0
悄悄地计算为nan
并不意味着您可以偷懒而不检查0.0 /0.0
在它发生之前。1 通过
x != x
检查nan
有时是不可靠的(x != x
被一些破坏的优化编译器剔除IEEE 合规性,特别是当启用-ffast-math
开关时)。nan prevention
My answer to this question is don't use retroactive checks for
nan
. Use preventive checks for divisions of the form0.0/0.0
instead.nan
results from the operation0.f/0.f
, or0.0/0.0
.nan
is a terrible nemesis to the stability of your code that must be detected and prevented very carefully1. The properties ofnan
that are different from normal numbers:nan
is toxic, (5*nan
=nan
)nan
is not equal to anything, not even itself (nan
!=nan
)nan
not greater than anything (nan
!> 0)nan
is not less than anything (nan
!< 0)The last 2 properties listed are counter-logical and will result in odd behavior of code that relies on comparisons with a
nan
number (the 3rd last property is odd too but you're probably not ever going to seex != x ?
in your code (unless you are checking for nan (unreliably))).In my own code, I noticed that
nan
values tend to produce difficult to find bugs. (Note how this is not the case forinf
or-inf
. (-inf
< 0) returnsTRUE
, ( 0 <inf
) returns TRUE, and even (-inf
<inf
) returns TRUE. So, in my experience, the behavior of the code is often still as desired).what to do under nan
What you want to happen under
0.0/0.0
must be handled as a special case, but what you do must depend on the numbers you expect to come out of the code.In the example above, the result of (
0.f/FLT_MIN
) will be0
, basically. You may want0.0/0.0
to generateHUGE
instead. So,So in the above, if x were
0.f
,inf
would result (which has pretty good/nondestructive behavior as mentioned above actually).Remember, integer division by 0 causes a runtime exception. So you must always check for integer division by 0. Just because
0.0/0.0
quietly evaluates tonan
doesn't mean you can be lazy and not check for0.0/0.0
before it happens.1 Checks for
nan
viax != x
are sometimes unreliable (x != x
being stripped out by some optimizing compilers that break IEEE compliance, specifically when the-ffast-math
switch is enabled).如果
sizeof(int)
为 4 并且sizeof(long long)
为 8,则此方法有效。在运行时,它只是比较,转换不需要任何时间。 它只是更改比较标志配置来检查相等性。
This works if
sizeof(int)
is 4 andsizeof(long long)
is 8.During run time it is only comparison, castings do not take any time. It just changes comparison flags configuration to check equality.
不依赖于所使用的 NaN 的特定 IEEE 表示的可能解决方案如下:
A possible solution that would not depend on the specific IEEE representation for NaN used would be the following:
考虑到 (x != x) 并不总是保证 NaN (例如使用 -ffast-math 选项),我一直在使用:
数字不能同时是 < 0 且 >= 0,所以实际上只有当数字既不小于也不大于或等于 0 时,此检查才会通过。 这基本上根本就没有数字,或者 NaN。
如果您愿意,也可以使用它:
但我不确定 -ffast-math 如何影响它,所以您的里程可能会有所不同。
Considering that (x != x) is not always guaranteed for NaN (such as if using the -ffast-math option), I've been using:
Numbers can't be both < 0 and >= 0, so really this check only passes if the number is neither less than, nor greater than or equal to zero. Which is basically no number at all, or NaN.
You could also use this if you prefer:
I'm not sure how this is affected by -ffast-math though, so your mileage may vary.
对我来说,解决方案可能是一个宏,使其显式内联,从而足够快。
它也适用于任何浮动类型。 它基于这样一个事实:值不等于自身的唯一情况是该值不是数字。
As for me the solution could be a macro to make it explicitly inline and thus fast enough.
It also works for any float type. It bases on the fact that the only case when a value is not equals itself is when the value is not a number.
这有效:
输出:isnan
This works:
output: isnan
在我看来,最好的真正跨平台方法是使用联合并测试双精度的位模式以检查 NaN。
我还没有彻底测试这个解决方案,可能有一种更有效的方法来处理位模式,但我认为它应该有效。
It seems to me that the best truly cross-platform approach would be to use a union and to test the bit pattern of the double to check for NaNs.
I have not thoroughly tested this solution, and there may be a more efficient way of working with the bit patterns, but I think that it should work.
在 x86-64 上,您可以使用极其快速的方法来检查 NaN 和无穷大,无论
-ffast-math
编译器选项如何,该方法都可以工作。 (f != f
、std::isnan
、std::isinf
始终使用产生
)。false
-ffast-math通过检查最大指数可以轻松测试 NaN、无穷大和有限数。 infinity 是最大指数,尾数为零,NaN 是最大指数,尾数非零。 指数存储在最高符号位之后的下一位中,因此我们只需左移即可去掉符号位并使指数成为最高位,无需掩码(
operator&
)必要:isinf
和isfinite
的std
版本从.data< 加载 2 个
double/float
常量/code> 段,在最坏的情况下,它们可能会导致 2 次数据缓存未命中。 上述版本不加载任何数据,inf_double_shl1
和inf_float_shl1
常量被编码为立即操作数到汇编指令中。更快的
isnan2
只需 2 条汇编指令:使用
ucomisd<如果任何参数为 NaN,/code>
指令将设置奇偶校验标志。 这就是在未指定
-ffast-math
选项时std::isnan
的工作方式。On x86-64 you can have extremely fast methods for checking for NaN and infinity, which work regardless of
-ffast-math
compiler option. (f != f
,std::isnan
,std::isinf
always yieldfalse
with-ffast-math
).Testing for NaN, infinity and finite numbers can easily be done by checking for maximum exponent. infinity is maximum exponent with zero mantissa, NaN is maximum exponent and non-zero mantissa. The exponent is stored in the next bits after the topmost sign bit, so that we can just left shift to get rid of the sign bit and make the exponent the topmost bits, no masking (
operator&
) is necessary:The
std
versions ofisinf
andisfinite
load 2double/float
constants from.data
segment and in the worst case scenario they can cause 2 data cache misses. The above versions do not load any data,inf_double_shl1
andinf_float_shl1
constants get encoded as immediate operands into the assembly instructions.Faster
isnan2
is just 2 assembly instructions:Uses the fact that
ucomisd
instruction sets parity flag if any argument is NaN. This is howstd::isnan
works when no-ffast-math
options is specified.IEEE 标准说
当指数全为 1 时
和
尾数不为零,
该数字是
NaN
。Double 是
1
符号位、11
指数位和52
尾数位。稍微检查一下。
The IEEE standard says
when the exponent is all
1
sand
the mantissa is not zero,
the number is a
NaN
.Double is
1
sign bit,11
exponent bits and52
mantissa bits.Do a bit check.
正如上面的注释所说, a != a 在 g++ 和其他一些编译器中不起作用,但这个技巧应该可以。 它可能没有那么有效,但它仍然是一种方法:
基本上,在 g++ 中(虽然我不确定其他的),如果变量不是有效的整数/浮点, printf 会在 %d 或 %.f 格式上打印“nan”。 因此,此代码检查字符串的第一个字符是否为“n”(如“nan”)
As comments above state a != a will not work in g++ and some other compilers, but this trick should. It may not be as efficient, but it's still a way:
Basically, in g++ (I am not sure about others though) printf prints 'nan' on %d or %.f formats if variable is not a valid integer/float. Therefore this code is checking for the first character of string to be 'n' (as in "nan")
这通过检查它是否在双重限制内来检测 Visual Studio 中的无穷大和 NaN:
This detects infinity and also NaN in Visual Studio by checking it is within double limits: