是否存在isnan()函数?
注:我在MinGW(如果这有区别的话)。
我使用isnan()从<math.h>解决了这个问题,这在<cmath>中不存在,我一开始是#包括在内的。
是否存在isnan()函数?
注:我在MinGW(如果这有区别的话)。
我使用isnan()从<math.h>解决了这个问题,这在<cmath>中不存在,我一开始是#包括在内的。
当前回答
第一个解决方案:如果您使用c++ 11
既然问了这个问题,就有了一些新的发展:重要的是要知道std::isnan()是c++ 11的一部分
剧情简介
在header <cmath>中定义
bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)
确定给定的浮点数参数是否为非数字(NaN)。
参数
参数:浮点值
返回值
如果arg是NaN则为true,否则为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将为假。
然而,最后一个选项可能不适用于每个编译器和某些设置(特别是优化设置),所以在最后的手段,你总是可以检查位模式…
其他回答
第一个解决方案:如果您使用c++ 11
既然问了这个问题,就有了一些新的发展:重要的是要知道std::isnan()是c++ 11的一部分
剧情简介
在header <cmath>中定义
bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)
确定给定的浮点数参数是否为非数字(NaN)。
参数
参数:浮点值
返回值
如果arg是NaN则为true,否则为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将为假。
然而,最后一个选项可能不适用于每个编译器和某些设置(特别是优化设置),所以在最后的手段,你总是可以检查位模式…
您可以使用在limits标准库中定义的numeric_limits<float>::quiet_NaN()进行测试。double有一个单独的常数。
#include <iostream>
#include <math.h>
#include <limits>
using namespace std;
int main( )
{
cout << "The quiet NaN for type float is: "
<< numeric_limits<float>::quiet_NaN( )
<< endl;
float f_nan = numeric_limits<float>::quiet_NaN();
if( isnan(f_nan) )
{
cout << "Float was Not a Number: " << f_nan << endl;
}
return 0;
}
我不知道这是否适用于所有平台,因为我只在Linux上用g++进行了测试。
根据IEEE标准,NaN值有一个奇怪的性质,涉及它们的比较总是假的。也就是说,对于浮点数f, f != f只有在f为NaN时才为真。
请注意,正如下面的一些评论所指出的,并不是所有编译器在优化代码时都尊重这一点。
对于任何声称使用IEEE浮点数的编译器,这个技巧都应该有效。但我不能保证它在实践中会起作用。如果有疑问,请检查编译器。
Boost中还提供了一个仅头文件的库,该库具有处理浮点数据类型的简洁工具
#include <boost/math/special_functions/fpclassify.hpp>
你会得到以下函数:
template <class T> bool isfinite(T z);
template <class T> bool isinf(T t);
template <class T> bool isnan(T t);
template <class T> bool isnormal(T t);
如果你有时间,那么看看Boost的整个数学工具包,它有许多有用的工具,并且正在快速增长。
此外,当处理浮点和非浮点时,查看数字转换可能是一个好主意。
南预防
我对这个问题的回答是不要对nan使用追溯检查。取而代之的是对表单0.0/0.0的划分使用预防性检查。
#include <float.h>
float x=0.f ; // I'm gonna divide by x!
if( !x ) // Wait! Let me check if x is 0
x = FLT_MIN ; // oh, since x was 0, i'll just make it really small instead.
float y = 0.f / x ; // whew, `nan` didn't appear.
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数比较的代码的奇怪行为(最后3个属性也很奇怪,但您可能永远不会看到x != x ?)在你的代码中(除非你在检查nan(不可靠))。
在我自己的代码中,我注意到nan值往往会产生难以发现的错误。(请注意,这不是inf或-inf的情况。(-inf < 0)返回TRUE, (0 < inf)返回TRUE,甚至(-inf < inf)返回TRUE。因此,在我的经验中,代码的行为通常仍然是理想的)。
在奶奶手下该怎么办
您希望在0.0/0.0下发生的事情必须作为特殊情况处理,但是您所做的事情必须取决于您期望从代码中得到的数字。
在上面的例子中,(0.f/FLT_MIN)的结果基本上是0。你可能想让0.0/0.0生成HUGE。所以,
float x=0.f, y=0.f, z;
if( !x && !y ) // 0.f/0.f case
z = FLT_MAX ; // biggest float possible
else
z = y/x ; // regular division.
在上面,如果x = 0。F, inf会导致(实际上如上所述,它具有相当好的/非破坏性行为)。
记住,整数除以0会导致运行时异常。所以你必须总是检查整数除以0。仅仅因为0.0/0.0悄悄地计算为nan并不意味着您可以偷懒,在它发生之前不检查0.0/0.0。
通过x != x检查nan有时是不可靠的(x != x被一些破坏IEEE遵从性的优化编译器剥离,特别是当- fast-math开关启用时)。