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; } 根据IEEE标准,NaN值具有奇
我通过使用
中的isnan()解决了这个问题,它在
中不存在,我最初是\include
ing。如果编译器支持c99扩展,那么就有一个std::isnan,但我不确定mingw是否支持
下面是一个小函数,如果您的编译器没有标准函数,它应该可以工作:
bool custom_isnan(double var)
{
volatile double d = var;
return d != d;
}
根据IEEE标准,NaN值具有奇怪的特性,即涉及它们的比较总是错误的。也就是说,对于浮点f,
f!=f
仅当f为NaN时才为真
请注意,正如下面的一些评论所指出的,并不是所有编译器在优化代码时都遵守这一点
对于任何声称使用IEEE浮点的编译器来说,这个技巧应该是有效的。但我不能保证它在实践中会起作用。如果有疑问,请咨询编译器。您可以使用
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()
{
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提供的整个数学工具包,它有很多有用的工具,并且正在快速增长
另外,在处理浮点和非浮点时,最好查看。没有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上方法:POSIX <强> >代码> ISNAN <代码>宏< /强>,C++ 0x>强>代码> ISNAN < /CARD>函数模板<强>,或VisualC++ >强> >代码> IsNAN< <代码>函数< /St>>/P>
不幸的是,检测使用哪一个是相当不切实际的
不幸的是,没有可靠的方法来检测您是否有IEEE 754与NAN的表示形式。标准库提供了一种官方的方式(numeric\u limits::is\u iec559
)。但在实践中,诸如g++之类的编译器会搞砸这一点
理论上可以简单地使用<强> <代码> x.x>代码> <强>,但是编译器如g++和VisualC++将其上调。
因此,最后,测试特定的位模式,假设(并希望在某个时候强制执行!)一个特定的表示,如IEEE 754
编辑:以“g++之类的编译器……搞砸了”为例,考虑
#include <limits>
#include <assert.h>
void foo( double a, double b )
{
assert( a != b );
}
int main()
{
typedef std::numeric_limits<double> Info;
double const nan1 = Info::quiet_NaN();
double const nan2 = Info::quiet_NaN();
foo( nan1, nan2 );
}
#包括
#包括
无效foo(双a,双b)
{
断言(a!=b);
}
int main()
{
typedef标准::数字限制信息;
双常量nan1=Info::quiet_NaN();
双常量nan2=Info::quiet_NaN();
富(nan1,nan2);;
}
使用g++(TDM-2 mingw32)4.4.1编译:
C:\test>键入“C:\Program Files\@commands\gnuc.bat”
@rem-finput字符集=windows-1252
@g++-O-pedantic-std=c++98-Wall-Wwrite字符串%*-Wno long
C:\test>gnuc x.cpp
C:\test>a&&echo工作…|| echo!失败
作品
C:\test>gnuc x.cpp——快速数学
C:\test>a&&echo工作…|| echo!失败
断言失败:a!=b,文件x.cpp,第6行
此应用程序已请求运行时以异常方式终止它。
有关更多信息,请联系应用程序的支持团队。
!失败
C:\test>_
以下代码使用NAN(所有指数位集,至少一个分数位集)的定义,并假设sizeof(int)=sizeof(float)=4。有关详细信息,您可以在Wikipedia中查找NAN
bool-IsNan(浮点值)
{
返回((*(UINT*)和值)&0x7fffffff)>0x7f80000;
}
不依赖于所用NaN的特定IEEE表示的可能解决方案如下:
template<class T>
bool isnan( T f ) {
T _nan = (T)0.0/(T)0.0;
return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}
模板
布尔伊斯南(T f){
T_nan=(T)0.0/(T)0.0;
返回0==memcmp((void*)&f,(void*)&n,sizeof(T))
C:\test> type "C:\Program Files\@commands\gnuc.bat"
@rem -finput-charset=windows-1252
@g++ -O -pedantic -std=c++98 -Wall -Wwrite-strings %* -Wno-long-long
C:\test> gnuc x.cpp
C:\test> a && echo works... || echo !failed
works...
C:\test> gnuc x.cpp --fast-math
C:\test> a && echo works... || echo !failed
Assertion failed: a != b, file x.cpp, line 6
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
!failed
C:\test> _
template<class T>
bool isnan( T f ) {
T _nan = (T)0.0/(T)0.0;
return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}
#ifndef isnan
#define isnan(a) (a != a)
#endif
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;