C++ 检查C+中的双精度(或浮点)是否为NaN+;
是否有isnan()函数 附言:我在(如果这有区别的话)C++ 检查C+中的双精度(或浮点)是否为NaN+;,c++,double,nan,C++,Double,Nan,是否有isnan()函数 附言:我在(如果这有区别的话) 我通过使用中的isnan()解决了这个问题,它在中不存在,我最初是\includeing。如果编译器支持c99扩展,那么就有一个std::isnan,但我不确定mingw是否支持 下面是一个小函数,如果您的编译器没有标准函数,它应该可以工作: bool custom_isnan(double var) { volatile double d = var; return d != d; } 如果您的编译器支持c99扩展,那
我通过使用
中的isnan()解决了这个问题,它在
中不存在,我最初是\include
ing。如果编译器支持c99扩展,那么就有一个std::isnan,但我不确定mingw是否支持
下面是一个小函数,如果您的编译器没有标准函数,它应该可以工作:
bool custom_isnan(double var)
{
volatile double d = var;
return d != d;
}
如果您的编译器支持c99扩展,那么就有一个std::isnan,但我不确定mingw是否支持 下面是一个小函数,如果您的编译器没有标准函数,它应该可以工作:
bool custom_isnan(double var)
{
volatile double d = var;
return d != d;
}
根据IEEE标准,NaN值具有奇怪的特性,即涉及它们的比较总是错误的。也就是说,对于浮点f,
f!=f
仅当f为NaN时才为真
请注意,正如下面的一些评论所指出的,并不是所有编译器在优化代码时都遵守这一点
对于任何声称使用IEEE浮点的编译器来说,这个技巧应该是有效的。但我不能保证它在实践中会起作用。如果有疑问,请咨询您的编译器。根据IEEE标准,NaN值有一个奇怪的特性,即涉及它们的比较总是错误的。也就是说,对于浮点f,
f!=f
仅当f为NaN时才为真
请注意,正如下面的一些评论所指出的,并不是所有编译器在优化代码时都遵守这一点
对于任何声称使用IEEE浮点的编译器来说,这个技巧应该是有效的。但我不能保证它在实践中会起作用。如果有疑问,请咨询编译器。您可以使用
isnan()
函数,但需要包含C数学库
#include <cmath>
您可以使用
isnan()
函数,但需要包含C数学库
#include <cmath>
您可以使用标准库中定义的
numeric\u limits::quiet\u 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;
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
cout您可以使用标准库中定义的数值限制::quiet\u 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;
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
coutBoost中也有一个简洁的工具来处理浮点数据类型
#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);
模板bool是有限的(tz);
模板bool-isinf(T);
模板bool-isnan(T);
模板布尔值正常(T);
若你们有时间,那个么看看Boost提供的整个数学工具包,它有很多有用的工具,并且正在快速增长
另外,在处理浮点和非浮点数据时,最好看看。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);
模板bool是有限的(tz);
模板bool-isinf(T);
模板bool-isnan(T);
模板布尔值正常(T);
若你们有时间,那个么看看Boost提供的整个数学工具包,它有很多有用的工具,并且正在快速增长
另外,在处理浮点和非浮点时,最好查看。没有isnan()在当前C++标准库中可用的函数:/Cuth>函数,它被引入并定义为非函数。C99定义的标准库元素不是当前C++标准ISO/IEC 1488∶1998的一部分,也不是更新ISO/IEC 1488∶2003。
2005提出了技术报告1,T1与C99到C++的兼容性,尽管它从未正式成为C++标准,但许多(或C++实现)提供了Tr1特征,所有的或仅是一些(Visual C++ 9不提供C99数学函数)。
如果TR1可用,则
cmath
包括C99元素,如isnan()
,isfinite()
,等等。但它们被定义为函数,而不是宏,通常在std::TR1::
命名空间中,尽管有许多实现(例如Linux上的GCC 4+或Mac OS X 10.5+上的XCode)将它们直接注入std::
,因此std::isnan
定义良好
<> P. >,C++的一些实现仍然使C99代码“ISNAND”(/Cuth-Ge宏)可用于C++(包括通过代码> CMASUD/CODE >或Max.H/COD>),这可能会引起更多混乱,开发人员可能会认为这是一种标准行为。
C++中的一个注释,如上所述,它不提供<代码> STD::ISNAN <代码>既不<代码> STD::Tr1::ISNAN < /C> >,但它提供了一个扩展函数,定义为 > iSn()/<代码>,这是自以来可用的。
在XCode上,还有更多的乐趣。如前所述,GCC 4+定义了std::isnan
。对于较旧版本的编译器和库形式的XCode,似乎(这里是),我还没有机会检查自己)定义了两个函数,\u inline\u isnand()
在Intel上和\u isnand()
在Power PC上。没有isnan()在当前C++标准库中可用的函数:/Cuth>函数,它被引入并定义为非函数。C99定义的标准库元素不是当前C++标准ISO/IEC 1488∶1998的一部分,也不是更新ISO/IEC 1488∶2003。
2005提出了技术报告1,T1与C99到C++的兼容性,尽管它从未正式成为C++标准,但许多(或C++实现)提供了Tr1特征,所有的或仅是一些(Visual C++ 9不提供C99数学函数)。
如果TR1可用,则
cmath
包括C99元素,如isnan()
,isfinite()
,等等,但它们被定义为funct
bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)
bool IsNan(float a)
{
char s[4];
sprintf(s, "%.3f", a);
if (s[0]=='n') return true;
else return false;
}
#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.
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.
inline bool IsNan(float f)
{
const uint32 u = *(uint32*)&f;
return (u&0x7F800000) == 0x7F800000 && (u&0x7FFFFF); // Both NaN and qNan.
}
inline bool IsNan(double d)
{
const uint64 u = *(uint64*)&d;
return (u&0x7FF0000000000000ULL) == 0x7FF0000000000000ULL && (u&0xFFFFFFFFFFFFFULL);
}
#include <iostream>
#include <math.h>
using namespace std;
int main ()
{
char ch='a';
double val = nan(&ch);
if(isnan(val))
cout << "isnan" << endl;
return 0;
}
#define IS_NAN(x) (((x) < 0) == ((x) >= 0))
#define IS_NAN(x) (!((x)<0) && !((x)>=0)
#include <stdint.h>
#include <stdio.h>
union NaN
{
uint64_t bits;
double num;
};
int main()
{
//Test if a double is NaN
double d = 0.0 / 0.0;
union NaN n;
n.num = d;
if((n.bits | 0x800FFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFF)
{
printf("NaN: %f", d);
}
return 0;
}
#include <cmath> // std::isnan, std::fpclassify
#include <iostream>
#include <iomanip> // std::setw
#include <limits>
#include <limits.h> // CHAR_BIT
#include <sstream>
#include <stdint.h> // uint64_t
using namespace std;
#define TEST( x, expr, expected ) \
[&](){ \
const auto value = x; \
const bool result = expr; \
ostringstream stream; \
stream << boolalpha << #x " = " << x << ", (" #expr ") = " << result; \
cout \
<< setw( 60 ) << stream.str() << " " \
<< (result == expected? "Success" : "FAILED") \
<< endl; \
}()
#define TEST_ALL_VARIABLES( expression ) \
TEST( v, expression, true ); \
TEST( u, expression, false ); \
TEST( w, expression, false )
using Fp_info = numeric_limits<double>;
inline auto is_ieee754_nan( double const x )
-> bool
{
static constexpr bool is_claimed_ieee754 = Fp_info::is_iec559;
static constexpr int n_bits_per_byte = CHAR_BIT;
using Byte = unsigned char;
static_assert( is_claimed_ieee754, "!" );
static_assert( n_bits_per_byte == 8, "!" );
static_assert( sizeof( x ) == sizeof( uint64_t ), "!" );
#ifdef _MSC_VER
uint64_t const bits = reinterpret_cast<uint64_t const&>( x );
#else
Byte bytes[sizeof(x)];
memcpy( bytes, &x, sizeof( x ) );
uint64_t int_value;
memcpy( &int_value, bytes, sizeof( x ) );
uint64_t const& bits = int_value;
#endif
static constexpr uint64_t sign_mask = 0x8000000000000000;
static constexpr uint64_t exp_mask = 0x7FF0000000000000;
static constexpr uint64_t mantissa_mask = 0x000FFFFFFFFFFFFF;
(void) sign_mask;
return (bits & exp_mask) == exp_mask and (bits & mantissa_mask) != 0;
}
auto main()
-> int
{
double const v = Fp_info::quiet_NaN();
double const u = 3.14;
double const w = Fp_info::infinity();
cout << boolalpha << left;
cout << "Compiler claims IEEE 754 = " << Fp_info::is_iec559 << endl;
cout << endl;;
TEST_ALL_VARIABLES( std::isnan(value) ); cout << endl;
TEST_ALL_VARIABLES( (fpclassify(value) == FP_NAN) ); cout << endl;
TEST_ALL_VARIABLES( (value != value) ); cout << endl;
TEST_ALL_VARIABLES( (value == Fp_info::quiet_NaN()) ); cout << endl;
TEST_ALL_VARIABLES( (ilogb(value) == FP_ILOGBNAN) ); cout << endl;
TEST_ALL_VARIABLES( isunordered(1.2345, value) ); cout << endl;
TEST_ALL_VARIABLES( is_ieee754_nan( value ) );
}
[C:\my\forums\so\282 (detect NaN)]
> g++ --version | find "++"
g++ (x86_64-win32-sjlj-rev1, Built by MinGW-W64 project) 6.3.0
[C:\my\forums\so\282 (detect NaN)]
> g++ foo.cpp && a
Compiler claims IEEE 754 = true
v = nan, (std::isnan(value)) = true Success
u = 3.14, (std::isnan(value)) = false Success
w = inf, (std::isnan(value)) = false Success
v = nan, ((fpclassify(value) == 0x0100)) = true Success
u = 3.14, ((fpclassify(value) == 0x0100)) = false Success
w = inf, ((fpclassify(value) == 0x0100)) = false Success
v = nan, ((value != value)) = true Success
u = 3.14, ((value != value)) = false Success
w = inf, ((value != value)) = false Success
v = nan, ((value == Fp_info::quiet_NaN())) = false FAILED
u = 3.14, ((value == Fp_info::quiet_NaN())) = false Success
w = inf, ((value == Fp_info::quiet_NaN())) = false Success
v = nan, ((ilogb(value) == ((int)0x80000000))) = true Success
u = 3.14, ((ilogb(value) == ((int)0x80000000))) = false Success
w = inf, ((ilogb(value) == ((int)0x80000000))) = false Success
v = nan, (isunordered(1.2345, value)) = true Success
u = 3.14, (isunordered(1.2345, value)) = false Success
w = inf, (isunordered(1.2345, value)) = false Success
v = nan, (is_ieee754_nan( value )) = true Success
u = 3.14, (is_ieee754_nan( value )) = false Success
w = inf, (is_ieee754_nan( value )) = false Success
[C:\my\forums\so\282 (detect NaN)]
> g++ foo.cpp -ffast-math && a
Compiler claims IEEE 754 = true
v = nan, (std::isnan(value)) = false FAILED
u = 3.14, (std::isnan(value)) = false Success
w = inf, (std::isnan(value)) = false Success
v = nan, ((fpclassify(value) == 0x0100)) = false FAILED
u = 3.14, ((fpclassify(value) == 0x0100)) = false Success
w = inf, ((fpclassify(value) == 0x0100)) = false Success
v = nan, ((value != value)) = false FAILED
u = 3.14, ((value != value)) = false Success
w = inf, ((value != value)) = false Success
v = nan, ((value == Fp_info::quiet_NaN())) = true Success
u = 3.14, ((value == Fp_info::quiet_NaN())) = true FAILED
w = inf, ((value == Fp_info::quiet_NaN())) = true FAILED
v = nan, ((ilogb(value) == ((int)0x80000000))) = true Success
u = 3.14, ((ilogb(value) == ((int)0x80000000))) = false Success
w = inf, ((ilogb(value) == ((int)0x80000000))) = false Success
v = nan, (isunordered(1.2345, value)) = false FAILED
u = 3.14, (isunordered(1.2345, value)) = false Success
w = inf, (isunordered(1.2345, value)) = false Success
v = nan, (is_ieee754_nan( value )) = true Success
u = 3.14, (is_ieee754_nan( value )) = false Success
w = inf, (is_ieee754_nan( value )) = false Success
[C:\my\forums\so\282 (detect NaN)]
> _
[C:\my\forums\so\282 (detect NaN)]
> cl /nologo- 2>&1 | find "++"
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23725 for x86
[C:\my\forums\so\282 (detect NaN)]
> cl foo.cpp /Feb && b
foo.cpp
Compiler claims IEEE 754 = true
v = nan, (std::isnan(value)) = true Success
u = 3.14, (std::isnan(value)) = false Success
w = inf, (std::isnan(value)) = false Success
v = nan, ((fpclassify(value) == 2)) = true Success
u = 3.14, ((fpclassify(value) == 2)) = false Success
w = inf, ((fpclassify(value) == 2)) = false Success
v = nan, ((value != value)) = true Success
u = 3.14, ((value != value)) = false Success
w = inf, ((value != value)) = false Success
v = nan, ((value == Fp_info::quiet_NaN())) = false FAILED
u = 3.14, ((value == Fp_info::quiet_NaN())) = false Success
w = inf, ((value == Fp_info::quiet_NaN())) = false Success
v = nan, ((ilogb(value) == 0x7fffffff)) = true Success
u = 3.14, ((ilogb(value) == 0x7fffffff)) = false Success
w = inf, ((ilogb(value) == 0x7fffffff)) = true FAILED
v = nan, (isunordered(1.2345, value)) = true Success
u = 3.14, (isunordered(1.2345, value)) = false Success
w = inf, (isunordered(1.2345, value)) = false Success
v = nan, (is_ieee754_nan( value )) = true Success
u = 3.14, (is_ieee754_nan( value )) = false Success
w = inf, (is_ieee754_nan( value )) = false Success
[C:\my\forums\so\282 (detect NaN)]
> cl foo.cpp /Feb /fp:fast && b
foo.cpp
Compiler claims IEEE 754 = true
v = nan, (std::isnan(value)) = true Success
u = 3.14, (std::isnan(value)) = false Success
w = inf, (std::isnan(value)) = false Success
v = nan, ((fpclassify(value) == 2)) = true Success
u = 3.14, ((fpclassify(value) == 2)) = false Success
w = inf, ((fpclassify(value) == 2)) = false Success
v = nan, ((value != value)) = true Success
u = 3.14, ((value != value)) = false Success
w = inf, ((value != value)) = false Success
v = nan, ((value == Fp_info::quiet_NaN())) = false FAILED
u = 3.14, ((value == Fp_info::quiet_NaN())) = false Success
w = inf, ((value == Fp_info::quiet_NaN())) = false Success
v = nan, ((ilogb(value) == 0x7fffffff)) = true Success
u = 3.14, ((ilogb(value) == 0x7fffffff)) = false Success
w = inf, ((ilogb(value) == 0x7fffffff)) = true FAILED
v = nan, (isunordered(1.2345, value)) = true Success
u = 3.14, (isunordered(1.2345, value)) = false Success
w = inf, (isunordered(1.2345, value)) = false Success
v = nan, (is_ieee754_nan( value )) = true Success
u = 3.14, (is_ieee754_nan( value )) = false Success
w = inf, (is_ieee754_nan( value )) = false Success
[C:\my\forums\so\282 (detect NaN)]
> _
//#include <float.h>
double x, y = -1.1; x = sqrt(y);
if (x >= DBL_MIN && x <= DBL_MAX )
cout << "DETECTOR-2 of errors FAILS" << endl;
else
cout << "DETECTOR-2 of errors OK" << endl;