How do I put condition for undefined value in c++? [duplicate] - c++

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 #includeing at first.

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.

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 like isnan(), isfinite(), etc. but they are defined as functions, not macros, usually in std::tr1:: namespace, though many implementations (i.e. GCC 4+ on Linux or in XCode on Mac OS X 10.5+) inject them directly to std::, so std::isnan is well defined.
Moreover, some implementations of C++ still make C99 isnan() macro available for C++ (included through cmath or math.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 neither std::tr1::isnan, but it provides an extension function defined as _isnan() which has been available since Visual C++ 6.0
On 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.

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++11
Synopsis
Defined in header <cmath>
bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)
Determines if the given floating point number arg is not-a-number (NaN).
Parameters
arg: floating point value
Return value
true if arg is NaN, false otherwise
Reference
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 of x 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 that NaN is not equal to itself: i.e. x == x will be false for x being NaN.
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 ...

There is also a header-only library present in Boost that have neat tools to deal with floating point datatypes
#include <boost/math/special_functions/fpclassify.hpp>
You get the following functions:
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);
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.

There are three "official" ways: posix isnan macro, c++0x isnan 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
#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 );
}
Compiling with g++ (TDM-2 mingw32) 4.4.1:
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> _

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:
bool custom_isnan(double var)
{
volatile double d = var;
return d != d;
}

You can use numeric_limits<float>::quiet_NaN( ) defined in the limits standard library to test with. There's a separate constant defined for 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;
}
I don't know if this works on all platforms, as I only tested with g++ on Linux.

You can use the isnan() function, but you need to include the C math library.
#include <cmath>
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.
inline bool isnan(double x) {
return x != x;
}

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 check v != 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 the
Posix 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 returns false 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.
#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 ) );
}
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):
[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)]
> _
Results with Visual C++:
[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)]
> _
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.

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 prevention
My answer to this question is don't use retroactive checks for nan. Use preventive checks for divisions of the form 0.0/0.0 instead.
#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 results from the operation 0.f/0.f, or 0.0/0.0. nan is a terrible nemesis to the stability of your code that must be detected and prevented very carefully1. The properties of nan 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 see x != 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 for inf or -inf. (-inf < 0) returns TRUE, ( 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 be 0, basically. You may want 0.0/0.0 to generate HUGE instead. So,
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.
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 to nan doesn't mean you can be lazy and not check for 0.0/0.0 before it happens.
1 Checks for nan via x != 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).

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);
}
This works if sizeof(int) is 4 and sizeof(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.

A possible solution that would not depend on the specific IEEE representation for NaN used would be the following:
template<class T>
bool isnan( T f ) {
T _nan = (T)0.0/(T)0.0;
return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}

Considering that (x != x) is not always guaranteed for NaN (such as if using the -ffast-math option), I've been using:
#define IS_NAN(x) (((x) < 0) == ((x) >= 0))
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:
#define IS_NAN(x) (!((x)<0) && !((x)>=0)
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.
#ifndef isnan
#define isnan(a) (a != a)
#endif

This works:
#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;
}
output: isnan

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.
#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;
}

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 yield false 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:
static inline uint64_t load_ieee754_rep(double a) {
uint64_t r;
static_assert(sizeof r == sizeof a, "Unexpected sizes.");
std::memcpy(&r, &a, sizeof a); // Generates movq instruction.
return r;
}
static inline uint32_t load_ieee754_rep(float a) {
uint32_t r;
static_assert(sizeof r == sizeof a, "Unexpected sizes.");
std::memcpy(&r, &a, sizeof a); // Generates movd instruction.
return r;
}
constexpr uint64_t inf_double_shl1 = UINT64_C(0xffe0000000000000);
constexpr uint32_t inf_float_shl1 = UINT32_C(0xff000000);
// The shift left removes the sign bit. The exponent moves into the topmost bits,
// so that plain unsigned comparison is enough.
static inline bool isnan2(double a) { return load_ieee754_rep(a) << 1 > inf_double_shl1; }
static inline bool isinf2(double a) { return load_ieee754_rep(a) << 1 == inf_double_shl1; }
static inline bool isfinite2(double a) { return load_ieee754_rep(a) << 1 < inf_double_shl1; }
static inline bool isnan2(float a) { return load_ieee754_rep(a) << 1 > inf_float_shl1; }
static inline bool isinf2(float a) { return load_ieee754_rep(a) << 1 == inf_float_shl1; }
static inline bool isfinite2(float a) { return load_ieee754_rep(a) << 1 < inf_float_shl1; }
The std versions of isinf and isfinite load 2 double/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 and inf_float_shl1 constants get encoded as immediate operands into the assembly instructions.
Faster isnan2 is just 2 assembly instructions:
bool isnan2(double a) {
bool r;
asm(".intel_syntax noprefix"
"\n\t ucomisd %1, %1"
"\n\t setp %b0"
"\n\t .att_syntax prefix"
: "=g" (r)
: "x" (a)
: "cc"
);
return r;
}
Uses the fact that ucomisd instruction sets parity flag if any argument is NaN. This is how std::isnan works when no -ffast-math options is specified.

The IEEE standard says
when the exponent is all 1s
and
the mantissa is not zero,
the number is a NaN.
Double is 1 sign bit, 11 exponent bits and 52 mantissa bits.
Do a bit check.

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:
bool IsNan(float a)
{
char s[4];
sprintf(s, "%.3f", a);
if (s[0]=='n') return true;
else return false;
}
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")

This detects infinity and also NaN in Visual Studio by checking it is within double limits:
//#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;

Related

Bool type True and False

I was playing around with the Bool type (Boolean Variable) and typed this:
#include <iostream>
int main(void)
{
using std::cout;
using std::cin;
using std::endl;
bool $ok = false & true;
if($ok == true)
{
cout << "The value is True." << endl;
}
else if($ok == false)
{
cout << "The value is false." << endl;
}
cin.get();
cin.get();
return 0;
}
I know the differences between using the bitwise operator & and the logical operator &&, but I do not see how this produces a false (0) value. I know if I swapped the bitwise operator and used a + the expression 0+1 would cause it to evaluate to true. Can someone explain why this:
bool $ok = false & true;
evaluates to false?
false=0(0x00000000)
true=1(0x00000001)
Now when we do bitwise and operator of (false & true)---(0&1=0).
0x00000000
& 0x00000001
-------------
0x00000000
Hence the result is 0(0x00000000)
Why would this be true? false converts to a 0-valued integer. true converts to a non-zero valued integer (normally 1, but this is not guaranteed). 0 & x for any x is always 0. 0 == false by definition of the integer/boolean interactions, thus the false branch is entered.
For what it's worth, over a domain of 0 and 1, with 0 as false and 1 as true, * maps to AND whereas + maps to OR. Given this, I'm not quite sure why you'd expect + and & to give the sameresults.
x * y != 0 iff x != 0 and y != 0
x + y != 0 iff x != 0 or y != 0
It's also worth mentioning that bit-wise operations on signed types tend to be a bad idea. If you're going to treat integers as bitfields, use unsigned integral types where the rules around the operations are much more natural and intuitive.
It's because false is 0 (when converted from boolean-land to integer-land), while true is 1 (when converted from boolean-land to integer-land).
false & true == 0 & 1 == 0 == false
false + true == 0 + 1 == 1 == true
If the magic of & is a mystery to you, there are lots of great resources on bitwise-and.

c++ additive identity unsafe example ( a+0.0 != a )

In MSDN article, it mentions when fp:fast mode is enabled, operations like additive identity (a±0.0 = a, 0.0-a = -a) are unsafe. Is there any example that a+0 != a under such mode?
EDIT: As someone mentioned below, this sort of issue normally comes up when doing comparison. My issue is from comparison, the psedocode looks like below:
for(i=0;i<v.len;i++)
{
sum+=v[i];
if( sum >= threshold) break;
}
It breaks after adding a value of 0 (v[i]). The v[i] is not from calculation, it is assigned. I understand if my v[i] is from calculation then rounding might come into play, but why even though I give v[i] a zero value, I still have this sum < threshold but sum + v[i] >= threshold?
The reason that it's "unsafe" is that what the compiler assumes to be zero may not really end up being zero, due to rounding errors.
Take this example which adds two floats on the edge of the precision which 32 bit floats allows:
float a = 33554430, b = 16777215;
float x = a + b;
float y = x - a - b;
float z = 1;
z = z + y;
With fp:fast, the compiler says "since x = a + b, y = x - a - b = 0, so 'z + y' is just z". However, due to rounding errors, y actually ends up being -1, not 0. So you would get a different result without fp:fast.
It's not saying something 'fixed' like, "if you set /fp:fast, and variable a happens to be 3.12345, then a+0 might not be a". It's saying that when you set /fp:fast, the compiler will take shortcuts that mean that if you compute a+0, and then compare that to what you stored for a, there is no guarantee that they'll be the same.
There is a great write up on this class of problems (which are endemic to floating point calculations on computers) here: http://www.parashift.com/c++-faq-lite/floating-point-arith2.html
If a is -0.0, then a + 0.0 is +0.0.
it mentions when fp:fast mode is enabled, operations like additive identity (a±0.0 = a, 0.0-a = -a) is unsafe.
What that article says is
Any of the following (unsafe) algebraic rules may be employed by the optimizer when the fp:fast mode is enabled:
And then it lists a±0.0 = a and 0.0-a = -a
It is not saying that these identities are unsafe when fp:fast is enabled. It is saying that these identities are not true for IEEE 754 floating point arithmetic but that /fp:fast will optimize as though they are true.
I'm not certain of an example that shows that a + 0.0 == a to be false (except for NaN, obviously), but IEEE 754 has a lot of subtleties, such as when intermediate values should be truncated. One possibility is that if you have some expression that includes + 0.0, that might result in a requirement under IEEE 754 to do truncation on an intermediate value, but that /fp:fast will generate code that doesn't do the truncation, and consequently later results may differ from what is strictly required by IEEE 754.
Using Pascal Cuoq's info here's a program that produces different output based on /fp:fast
#include <cmath>
#include <iostream>
int main() {
volatile double a = -0.0;
if (_copysign(1.0, a + 0.0) == _copysign(1.0, 0.0)) {
std::cout << "correct IEEE 754 results\n";
} else {
std::cout << "result not IEEE 754 conformant\n";
}
}
When built with /fp:fast the program outputs "result not IEEE 754 conformant" while building with /fp:strict cause the program to output "correct IEEE 754 results".

c++ rounding of numbers away from zero

Hi i want to round double numbers like this (away from zero) in C++:
4.2 ----> 5
5.7 ----> 6
-7.8 ----> -8
-34.2 ----> -35
What is the efficient way to do this?
inline double myround(double x)
{
return x < 0 ? floor(x) : ceil(x);
}
As mentioned in the article Huppie cites, this is best expressed as a template that works across all float types
See http://en.cppreference.com/w/cpp/numeric/math/floor and http://en.cppreference.com/w/cpp/numeric/math/floor
or, thanks to Pax, a non-function version:
x = (x < 0) ? floor(x) : ceil(x);
There is a nice article about a similar problem on CPlusPlus.com. The easy solution to your problem should be something like this:
double customRound( double value ) const {
return value < 0 ? floor( value ) : ceil( value );
}
A better solution is the one mentioned in the article, which uses a template:
//--------------------------------------------------------------------------
// symmetric round up
// Bias: away from zero
template <typename FloatType>
FloatType ceil0( const FloatType& value )
{
FloatType result = std::ceil( std::fabs( value ) );
return (value < 0.0) ? -result : result;
}
The x < 0 ? floor(x) : ceil(x); approach of Ruben Bartelink is good. Yet consider what happens with special cases of x = -0.0, x = NaN.
Rather than have myround(-0.0) potentially return +0.01 and have myround(NaN) return with a changed payload of the NaN, consider the below.
myround_alt(-0.0) returns -0.0.
myround_alt(NaN) more likely returns an unchanged payload NaN. Not-a-number stuff is tricky and not well defined. IAC, it is the myround_alt(-0.0) --> -0.0 I am seeking.
inline double myround_alt(double x) {
if (x > 0) return ceil(x);
if (x < 0) return floor(x);
return x;
}
1IEC 60559 floating-point arithmetic specifies ceil(±0) returns ±0 so this approach not needed with implementations that strictly follow that spec. Yet many C floating point implementation do not follow that (C does not require it) or fail in such comer cases like this.
try
double rounded = _copysign(ceil(abs(x)), x);

round() for float in C++

I need a simple floating point rounding function, thus:
double round(double);
round(0.1) = 0
round(-0.1) = 0
round(-0.9) = -1
I can find ceil() and floor() in the math.h - but not round().
Is it present in the standard C++ library under another name, or is it missing??
Editor's Note: The following answer provides a simplistic solution that contains several implementation flaws (see Shafik Yaghmour's answer for a full explanation). Note that C++11 includes std::round, std::lround, and std::llround as builtins already.
There's no round() in the C++98 standard library. You can write one yourself though. The following is an implementation of round-half-up:
double round(double d)
{
return floor(d + 0.5);
}
The probable reason there is no round function in the C++98 standard library is that it can in fact be implemented in different ways. The above is one common way but there are others such as round-to-even, which is less biased and generally better if you're going to do a lot of rounding; it's a bit more complex to implement though.
The C++03 standard relies on the C90 standard for what the standard calls the Standard C Library which is covered in the draft C++03 standard (closest publicly available draft standard to C++03 is N1804) section 1.2 Normative references:
The library described in clause 7 of ISO/IEC 9899:1990 and clause 7 of
ISO/IEC 9899/Amd.1:1995 is hereinafter called the Standard C
Library.1)
If we go to the C documentation for round, lround, llround on cppreference we can see that round and related functions are part of C99 and thus won't be available in C++03 or prior.
In C++11 this changes since C++11 relies on the C99 draft standard for C standard library and therefore provides std::round and for integral return types std::lround, std::llround :
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::round( 0.4 ) << " " << std::lround( 0.4 ) << " " << std::llround( 0.4 ) << std::endl ;
std::cout << std::round( 0.5 ) << " " << std::lround( 0.5 ) << " " << std::llround( 0.5 ) << std::endl ;
std::cout << std::round( 0.6 ) << " " << std::lround( 0.6 ) << " " << std::llround( 0.6 ) << std::endl ;
}
Another option also from C99 would be std::trunc which:
Computes nearest integer not greater in magnitude than arg.
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::trunc( 0.4 ) << std::endl ;
std::cout << std::trunc( 0.9 ) << std::endl ;
std::cout << std::trunc( 1.1 ) << std::endl ;
}
If you need to support non C++11 applications your best bet would be to use boost round, iround, lround, llround or boost trunc.
Rolling your own version of round is hard
Rolling your own is probably not worth the effort as Harder than it looks: rounding float to nearest integer, part 1, Rounding float to nearest integer, part 2 and Rounding float to nearest integer, part 3 explain:
For example a common roll your implementation using std::floor and adding 0.5 does not work for all inputs:
double myround(double d)
{
return std::floor(d + 0.5);
}
One input this will fail for is 0.49999999999999994, (see it live).
Another common implementation involves casting a floating point type to an integral type, which can invoke undefined behavior in the case where the integral part can not be represented in the destination type. We can see this from the draft C++ standard section 4.9 Floating-integral conversions which says (emphasis mine):
A prvalue of a floating point type can be converted to a prvalue of an
integer type. The conversion truncates; that is, the fractional part
is discarded. The behavior is undefined if the truncated value cannot
be represented in the destination type.[...]
For example:
float myround(float f)
{
return static_cast<float>( static_cast<unsigned int>( f ) ) ;
}
Given std::numeric_limits<unsigned int>::max() is 4294967295 then the following call:
myround( 4294967296.5f )
will cause overflow, (see it live).
We can see how difficult this really is by looking at this answer to Concise way to implement round() in C? which referencing newlibs version of single precision float round. It is a very long function for something which seems simple. It seems unlikely that anyone without intimate knowledge of floating point implementations could correctly implement this function:
float roundf(x)
{
int signbit;
__uint32_t w;
/* Most significant word, least significant word. */
int exponent_less_127;
GET_FLOAT_WORD(w, x);
/* Extract sign bit. */
signbit = w & 0x80000000;
/* Extract exponent field. */
exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
if (exponent_less_127 < 23)
{
if (exponent_less_127 < 0)
{
w &= 0x80000000;
if (exponent_less_127 == -1)
/* Result is +1.0 or -1.0. */
w |= ((__uint32_t)127 << 23);
}
else
{
unsigned int exponent_mask = 0x007fffff >> exponent_less_127;
if ((w & exponent_mask) == 0)
/* x has an integral value. */
return x;
w += 0x00400000 >> exponent_less_127;
w &= ~exponent_mask;
}
}
else
{
if (exponent_less_127 == 128)
/* x is NaN or infinite. */
return x + x;
else
return x;
}
SET_FLOAT_WORD(x, w);
return x;
}
On the other hand if none of the other solutions are usable newlib could potentially be an option since it is a well tested implementation.
Boost offers a simple set of rounding functions.
#include <boost/math/special_functions/round.hpp>
double a = boost::math::round(1.5); // Yields 2.0
int b = boost::math::iround(1.5); // Yields 2 as an integer
For more information, see the Boost documentation.
Edit: Since C++11, there are std::round, std::lround, and std::llround.
It may be worth noting that if you wanted an integer result from the rounding you don't need to pass it through either ceil or floor. I.e.,
int round_int( double r ) {
return (r > 0.0) ? (r + 0.5) : (r - 0.5);
}
It's available since C++11 in cmath (according to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf)
#include <cmath>
#include <iostream>
int main(int argc, char** argv) {
std::cout << "round(0.5):\t" << round(0.5) << std::endl;
std::cout << "round(-0.5):\t" << round(-0.5) << std::endl;
std::cout << "round(1.4):\t" << round(1.4) << std::endl;
std::cout << "round(-1.4):\t" << round(-1.4) << std::endl;
std::cout << "round(1.6):\t" << round(1.6) << std::endl;
std::cout << "round(-1.6):\t" << round(-1.6) << std::endl;
return 0;
}
Output:
round(0.5): 1
round(-0.5): -1
round(1.4): 1
round(-1.4): -1
round(1.6): 2
round(-1.6): -2
It's usually implemented as floor(value + 0.5).
Edit: and it's probably not called round since there are at least three rounding algorithms I know of: round to zero, round to closest integer, and banker's rounding. You are asking for round to closest integer.
There are 2 problems we are looking at:
rounding conversions
type conversion.
Rounding conversions mean rounding ± float/double to nearest floor/ceil float/double.
May be your problem ends here.
But if you are expected to return Int/Long, you need to perform type conversion, and thus "Overflow" problem might hit your solution. SO, do a check for error in your function
long round(double x) {
assert(x >= LONG_MIN-0.5);
assert(x <= LONG_MAX+0.5);
if (x >= 0)
return (long) (x+0.5);
return (long) (x-0.5);
}
#define round(x) ((x) < LONG_MIN-0.5 || (x) > LONG_MAX+0.5 ?\
error() : ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
from : http://www.cs.tut.fi/~jkorpela/round.html
A certain type of rounding is also implemented in Boost:
#include <iostream>
#include <boost/numeric/conversion/converter.hpp>
template<typename T, typename S> T round2(const S& x) {
typedef boost::numeric::conversion_traits<T, S> Traits;
typedef boost::numeric::def_overflow_handler OverflowHandler;
typedef boost::numeric::RoundEven<typename Traits::source_type> Rounder;
typedef boost::numeric::converter<T, S, Traits, OverflowHandler, Rounder> Converter;
return Converter::convert(x);
}
int main() {
std::cout << round2<int, double>(0.1) << ' ' << round2<int, double>(-0.1) << ' ' << round2<int, double>(-0.9) << std::endl;
}
Note that this works only if you do a to-integer conversion.
You could round to n digits precision with:
double round( double x )
{
const double sd = 1000; //for accuracy to 3 decimal places
return int(x*sd + (x<0? -0.5 : 0.5))/sd;
}
These days it shouldn't be a problem to use a C++11 compiler which includes a C99/C++11 math library. But then the question becomes: which rounding function do you pick?
C99/C++11 round() is often not actually the rounding function you want. It uses a funky rounding mode that rounds away from 0 as a tie-break on half-way cases (+-xxx.5000). If you do specifically want that rounding mode, or you're targeting a C++ implementation where round() is faster than rint(), then use it (or emulate its behaviour with one of the other answers on this question which took it at face value and carefully reproduced that specific rounding behaviour.)
round()'s rounding is different from the IEEE754 default round to nearest mode with even as a tie-break. Nearest-even avoids statistical bias in the average magnitude of numbers, but does bias towards even numbers.
There are two math library rounding functions that use the current default rounding mode: std::nearbyint() and std::rint(), both added in C99/C++11, so they're available any time std::round() is. The only difference is that nearbyint never raises FE_INEXACT.
Prefer rint() for performance reasons: gcc and clang both inline it more easily, but gcc never inlines nearbyint() (even with -ffast-math)
gcc/clang for x86-64 and AArch64
I put some test functions on Matt Godbolt's Compiler Explorer, where you can see source + asm output (for multiple compilers). For more about reading compiler output, see this Q&A, and Matt's CppCon2017 talk: “What Has My Compiler Done for Me Lately? Unbolting the Compiler's Lid”,
In FP code, it's usually a big win to inline small functions. Especially on non-Windows, where the standard calling convention has no call-preserved registers, so the compiler can't keep any FP values in XMM registers across a call. So even if you don't really know asm, you can still easily see whether it's just a tail-call to the library function or whether it inlined to one or two math instructions. Anything that inlines to one or two instructions is better than a function call (for this particular task on x86 or ARM).
On x86, anything that inlines to SSE4.1 roundsd can auto-vectorize with SSE4.1 roundpd (or AVX vroundpd). (FP->integer conversions are also available in packed SIMD form, except for FP->64-bit integer which requires AVX512.)
std::nearbyint():
x86 clang: inlines to a single insn with -msse4.1.
x86 gcc: inlines to a single insn only with -msse4.1 -ffast-math, and only on gcc 5.4 and earlier. Later gcc never inlines it (maybe they didn't realize that one of the immediate bits can suppress the inexact exception? That's what clang uses, but older gcc uses the same immediate as for rint when it does inline it)
AArch64 gcc6.3: inlines to a single insn by default.
std::rint:
x86 clang: inlines to a single insn with -msse4.1
x86 gcc7: inlines to a single insn with -msse4.1. (Without SSE4.1, inlines to several instructions)
x86 gcc6.x and earlier: inlines to a single insn with -ffast-math -msse4.1.
AArch64 gcc: inlines to a single insn by default
std::round:
x86 clang: doesn't inline
x86 gcc: inlines to multiple instructions with -ffast-math -msse4.1, requiring two vector constants.
AArch64 gcc: inlines to a single instruction (HW support for this rounding mode as well as IEEE default and most others.)
std::floor / std::ceil / std::trunc
x86 clang: inlines to a single insn with -msse4.1
x86 gcc7.x: inlines to a single insn with -msse4.1
x86 gcc6.x and earlier: inlines to a single insn with -ffast-math -msse4.1
AArch64 gcc: inlines by default to a single instruction
Rounding to int / long / long long:
You have two options here: use lrint (like rint but returns long, or long long for llrint), or use an FP->FP rounding function and then convert to an integer type the normal way (with truncation). Some compilers optimize one way better than the other.
long l = lrint(x);
int i = (int)rint(x);
Note that int i = lrint(x) converts float or double -> long first, and then truncates the integer to int. This makes a difference for out-of-range integers: Undefined Behaviour in C++, but well-defined for the x86 FP -> int instructions (which the compiler will emit unless it sees the UB at compile time while doing constant propagation, then it's allowed to make code that breaks if it's ever executed).
On x86, an FP->integer conversion that overflows the integer produces INT_MIN or LLONG_MIN (a bit-pattern of 0x8000000 or the 64-bit equivalent, with just the sign-bit set). Intel calls this the "integer indefinite" value. (See the cvttsd2si manual entry, the SSE2 instruction that converts (with truncation) scalar double to signed integer. It's available with 32-bit or 64-bit integer destination (in 64-bit mode only). There's also a cvtsd2si (convert with current rounding mode), which is what we'd like the compiler to emit, but unfortunately gcc and clang won't do that without -ffast-math.
Also beware that FP to/from unsigned int / long is less efficient on x86 (without AVX512). Conversion to 32-bit unsigned on a 64-bit machine is pretty cheap; just convert to 64-bit signed and truncate. But otherwise it's significantly slower.
x86 clang with/without -ffast-math -msse4.1: (int/long)rint inlines to roundsd / cvttsd2si. (missed optimization to cvtsd2si). lrint doesn't inline at all.
x86 gcc6.x and earlier without -ffast-math: neither way inlines
x86 gcc7 without -ffast-math: (int/long)rint rounds and converts separately (with 2 total instructions of SSE4.1 is enabled, otherwise with a bunch of code inlined for rint without roundsd). lrint doesn't inline.
x86 gcc with -ffast-math: all ways inline to cvtsd2si (optimal), no need for SSE4.1.
AArch64 gcc6.3 without -ffast-math: (int/long)rint inlines to 2 instructions. lrint doesn't inline
AArch64 gcc6.3 with -ffast-math: (int/long)rint compiles to a call to lrint. lrint doesn't inline. This may be a missed optimization unless the two instructions we get without -ffast-math are very slow.
If you ultimately want to convert the double output of your round() function to an int, then the accepted solutions of this question will look something like:
int roundint(double r) {
return (int)((r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5));
}
This clocks in at around 8.88 ns on my machine when passed in uniformly random values.
The below is functionally equivalent, as far as I can tell, but clocks in at 2.48 ns on my machine, for a significant performance advantage:
int roundint (double r) {
int tmp = static_cast<int> (r);
tmp += (r-tmp>=.5) - (r-tmp<=-.5);
return tmp;
}
Among the reasons for the better performance is the skipped branching.
Beware of floor(x+0.5). Here is what can happen for odd numbers in range [2^52,2^53]:
-bash-3.2$ cat >test-round.c <<END
#include <math.h>
#include <stdio.h>
int main() {
double x=5000000000000001.0;
double y=round(x);
double z=floor(x+0.5);
printf(" x =%f\n",x);
printf("round(x) =%f\n",y);
printf("floor(x+0.5)=%f\n",z);
return 0;
}
END
-bash-3.2$ gcc test-round.c
-bash-3.2$ ./a.out
x =5000000000000001.000000
round(x) =5000000000000001.000000
floor(x+0.5)=5000000000000002.000000
This is http://bugs.squeak.org/view.php?id=7134. Use a solution like the one of #konik.
My own robust version would be something like:
double round(double x)
{
double truncated,roundedFraction;
double fraction = modf(x, &truncated);
modf(2.0*fraction, &roundedFraction);
return truncated + roundedFraction;
}
Another reason to avoid floor(x+0.5) is given here.
There is no need to implement anything, so I'm not sure why so many answers involve defines, functions, or methods.
In C99
We have the following and and header <tgmath.h> for type-generic macros.
#include <math.h>
double round (double x);
float roundf (float x);
long double roundl (long double x);
If you cannot compile this, you have probably left out the math library. A command similar to this works on every C compiler I have (several).
gcc -lm -std=c99 ...
In C++11
We have the following and additional overloads in #include <cmath> that rely on IEEE double precision floating point.
#include <math.h>
double round (double x);
float round (float x);
long double round (long double x);
double round (T x);
There are equivalents in the std namespace too.
If you cannot compile this, you may be using C compilation instead of C++. The following basic command produces neither errors nor warnings with g++ 6.3.1, x86_64-w64-mingw32-g++ 6.3.0, clang-x86_64++ 3.8.0, and Visual C++ 2015 Community.
g++ -std=c++11 -Wall
With Ordinal Division
When dividing two ordinal numbers, where T is short, int, long, or another ordinal, the rounding expression is this.
T roundedQuotient = (2 * integerNumerator + 1)
/ (2 * integerDenominator);
Accuracy
There is no doubt that odd looking inaccuracies appear in floating point operations, but this is only when the numbers appear, and has little to do with rounding.
The source is not just the number of significant digits in the mantissa of the IEEE representation of a floating point number, it is related to our decimal thinking as humans.
Ten is the product of five and two, and 5 and 2 are relatively prime. Therefore the IEEE floating point standards cannot possibly be represented perfectly as decimal numbers for all binary digital representations.
This is not an issue with the rounding algorithms. It is mathematical reality that should be considered during the selection of types and the design of computations, data entry, and display of numbers. If an application displays the digits that show these decimal-binary conversion issues, then the application is visually expressing accuracy that does not exist in digital reality and should be changed.
Function double round(double) with the use of the modf function:
double round(double x)
{
using namespace std;
if ((numeric_limits<double>::max() - 0.5) <= x)
return numeric_limits<double>::max();
if ((-1*std::numeric_limits<double>::max() + 0.5) > x)
return (-1*std::numeric_limits<double>::max());
double intpart;
double fractpart = modf(x, &intpart);
if (fractpart >= 0.5)
return (intpart + 1);
else if (fractpart >= -0.5)
return intpart;
else
return (intpart - 1);
}
To be compile clean, includes "math.h" and "limits" are necessary. The function works according to a following rounding schema:
round of 5.0 is 5.0
round of 3.8 is 4.0
round of 2.3 is 2.0
round of 1.5 is 2.0
round of 0.501 is 1.0
round of 0.5 is 1.0
round of 0.499 is 0.0
round of 0.01 is 0.0
round of 0.0 is 0.0
round of -0.01 is -0.0
round of -0.499 is -0.0
round of -0.5 is -0.0
round of -0.501 is -1.0
round of -1.5 is -1.0
round of -2.3 is -2.0
round of -3.8 is -4.0
round of -5.0 is -5.0
If you need to be able to compile code in environments that support the C++11 standard, but also need to be able to compile that same code in environments that don't support it, you could use a function macro to choose between std::round() and a custom function for each system. Just pass -DCPP11 or /DCPP11 to the C++11-compliant compiler (or use its built-in version macros), and make a header like this:
// File: rounding.h
#include <cmath>
#ifdef CPP11
#define ROUND(x) std::round(x)
#else /* CPP11 */
inline double myRound(double x) {
return (x >= 0.0 ? std::floor(x + 0.5) : std::ceil(x - 0.5));
}
#define ROUND(x) myRound(x)
#endif /* CPP11 */
For a quick example, see http://ideone.com/zal709 .
This approximates std::round() in environments that aren't C++11-compliant, including preservation of the sign bit for -0.0. It may cause a slight performance hit, however, and will likely have issues with rounding certain known "problem" floating-point values such as 0.49999999999999994 or similar values.
Alternatively, if you have access to a C++11-compliant compiler, you could just grab std::round() from its <cmath> header, and use it to make your own header that defines the function if it's not already defined. Note that this may not be an optimal solution, however, especially if you need to compile for multiple platforms.
Based on Kalaxy's response, the following is a templated solution that rounds any floating point number to the nearest integer type based on natural rounding. It also throws an error in debug mode if the value is out of range of the integer type, thereby serving roughly as a viable library function.
// round a floating point number to the nearest integer
template <typename Arg>
int Round(Arg arg)
{
#ifndef NDEBUG
// check that the argument can be rounded given the return type:
if (
(Arg)std::numeric_limits<int>::max() < arg + (Arg) 0.5) ||
(Arg)std::numeric_limits<int>::lowest() > arg - (Arg) 0.5)
)
{
throw std::overflow_error("out of bounds");
}
#endif
return (arg > (Arg) 0.0) ? (int)(r + (Arg) 0.5) : (int)(r - (Arg) 0.5);
}
As pointed out in comments and other answers, the ISO C++ standard library did not add round() until ISO C++11, when this function was pulled in by reference to the ISO C99 standard math library.
For positive operands in [½, ub] round(x) == floor (x + 0.5), where ub is 223 for float when mapped to IEEE-754 (2008) binary32, and 252 for double when it is mapped to IEEE-754 (2008) binary64. The numbers 23 and 52 correspond to the number of stored mantissa bits in these two floating-point formats. For positive operands in [+0, ½) round(x) == 0, and for positive operands in (ub, +∞] round(x) == x. As the function is symmetric about the x-axis, negative arguments x can be handled according to round(-x) == -round(x).
This leads to the compact code below. It compiles into a reasonable number of machine instructions across various platforms. I observed the most compact code on GPUs, where my_roundf() requires about a dozen instructions. Depending on processor architecture and toolchain, this floating-point based approach could be either faster or slower than the integer-based implementation from newlib referenced in a different answer.
I tested my_roundf() exhaustively against the newlib roundf() implementation using Intel compiler version 13, with both /fp:strict and /fp:fast. I also checked that the newlib version matches the roundf() in the mathimf library of the Intel compiler. Exhaustive testing is not possible for double-precision round(), however the code is structurally identical to the single-precision implementation.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
float my_roundf (float x)
{
const float half = 0.5f;
const float one = 2 * half;
const float lbound = half;
const float ubound = 1L << 23;
float a, f, r, s, t;
s = (x < 0) ? (-one) : one;
a = x * s;
t = (a < lbound) ? x : s;
f = (a < lbound) ? 0 : floorf (a + half);
r = (a > ubound) ? x : (t * f);
return r;
}
double my_round (double x)
{
const double half = 0.5;
const double one = 2 * half;
const double lbound = half;
const double ubound = 1ULL << 52;
double a, f, r, s, t;
s = (x < 0) ? (-one) : one;
a = x * s;
t = (a < lbound) ? x : s;
f = (a < lbound) ? 0 : floor (a + half);
r = (a > ubound) ? x : (t * f);
return r;
}
uint32_t float_as_uint (float a)
{
uint32_t r;
memcpy (&r, &a, sizeof(r));
return r;
}
float uint_as_float (uint32_t a)
{
float r;
memcpy (&r, &a, sizeof(r));
return r;
}
float newlib_roundf (float x)
{
uint32_t w;
int exponent_less_127;
w = float_as_uint(x);
/* Extract exponent field. */
exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
if (exponent_less_127 < 23) {
if (exponent_less_127 < 0) {
/* Extract sign bit. */
w &= 0x80000000;
if (exponent_less_127 == -1) {
/* Result is +1.0 or -1.0. */
w |= ((uint32_t)127 << 23);
}
} else {
uint32_t exponent_mask = 0x007fffff >> exponent_less_127;
if ((w & exponent_mask) == 0) {
/* x has an integral value. */
return x;
}
w += 0x00400000 >> exponent_less_127;
w &= ~exponent_mask;
}
} else {
if (exponent_less_127 == 128) {
/* x is NaN or infinite so raise FE_INVALID by adding */
return x + x;
} else {
return x;
}
}
x = uint_as_float (w);
return x;
}
int main (void)
{
uint32_t argi, resi, refi;
float arg, res, ref;
argi = 0;
do {
arg = uint_as_float (argi);
ref = newlib_roundf (arg);
res = my_roundf (arg);
resi = float_as_uint (res);
refi = float_as_uint (ref);
if (resi != refi) { // check for identical bit pattern
printf ("!!!! arg=%08x res=%08x ref=%08x\n", argi, resi, refi);
return EXIT_FAILURE;
}
argi++;
} while (argi);
return EXIT_SUCCESS;
}
I use the following implementation of round in asm for x86 architecture and MS VS specific C++:
__forceinline int Round(const double v)
{
int r;
__asm
{
FLD v
FISTP r
FWAIT
};
return r;
}
UPD: to return double value
__forceinline double dround(const double v)
{
double r;
__asm
{
FLD v
FRNDINT
FSTP r
FWAIT
};
return r;
}
Output:
dround(0.1): 0.000000000000000
dround(-0.1): -0.000000000000000
dround(0.9): 1.000000000000000
dround(-0.9): -1.000000000000000
dround(1.1): 1.000000000000000
dround(-1.1): -1.000000000000000
dround(0.49999999999999994): 0.000000000000000
dround(-0.49999999999999994): -0.000000000000000
dround(0.5): 0.000000000000000
dround(-0.5): -0.000000000000000
Since C++ 11 simply:
#include <cmath>
std::round(1.1)
or to get int
static_cast<int>(std::round(1.1))
round_f for ARM with math
static inline float round_f(float value)
{
float rep;
asm volatile ("vrinta.f32 %0,%1" : "=t"(rep) : "t"(value));
return rep;
}
round_f for ARM without math
union f__raw {
struct {
uint32_t massa :23;
uint32_t order :8;
uint32_t sign :1;
};
int32_t i_raw;
float f_raw;
};
float round_f(float value)
{
union f__raw raw;
int32_t exx;
uint32_t ex_mask;
raw.f_raw = value;
exx = raw.order - 126;
if (exx < 0) {
raw.i_raw &= 0x80000000;
} else if (exx < 24) {
ex_mask = 0x00ffffff >> exx;
raw.i_raw += 0x00800000 >> exx;
if (exx == 0) ex_mask >>= 1;
raw.i_raw &= ~ex_mask;
};
return raw.f_raw;
};
Best way to rounding off a floating value by "n" decimal places, is as following with in O(1) time:-
We have to round off the value by 3 places i.e. n=3.So,
float a=47.8732355;
printf("%.3f",a);
// Convert the float to a string
// We might use stringstream, but it looks like it truncates the float to only
//5 decimal points (maybe that's what you want anyway =P)
float MyFloat = 5.11133333311111333;
float NewConvertedFloat = 0.0;
string FirstString = " ";
string SecondString = " ";
stringstream ss (stringstream::in | stringstream::out);
ss << MyFloat;
FirstString = ss.str();
// Take out how ever many decimal places you want
// (this is a string it includes the point)
SecondString = FirstString.substr(0,5);
//whatever precision decimal place you want
// Convert it back to a float
stringstream(SecondString) >> NewConvertedFloat;
cout << NewConvertedFloat;
system("pause");
It might be an inefficient dirty way of conversion but heck, it works lol. And it's good, because it applies to the actual float. Not just affecting the output visually.
I did this:
#include <cmath.h>
using namespace std;
double roundh(double number, int place){
/* place = decimal point. Putting in 0 will make it round to whole
number. putting in 1 will round to the
tenths digit.
*/
number *= 10^place;
int istack = (int)floor(number);
int out = number-istack;
if (out < 0.5){
floor(number);
number /= 10^place;
return number;
}
if (out > 0.4) {
ceil(number);
number /= 10^place;
return number;
}
}

Checking if a double (or float) is NaN in C++

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 #includeing at first.
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.
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 like isnan(), isfinite(), etc. but they are defined as functions, not macros, usually in std::tr1:: namespace, though many implementations (i.e. GCC 4+ on Linux or in XCode on Mac OS X 10.5+) inject them directly to std::, so std::isnan is well defined.
Moreover, some implementations of C++ still make C99 isnan() macro available for C++ (included through cmath or math.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 neither std::tr1::isnan, but it provides an extension function defined as _isnan() which has been available since Visual C++ 6.0
On 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.
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++11
Synopsis
Defined in header <cmath>
bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)
Determines if the given floating point number arg is not-a-number (NaN).
Parameters
arg: floating point value
Return value
true if arg is NaN, false otherwise
Reference
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 of x 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 that NaN is not equal to itself: i.e. x == x will be false for x being NaN.
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 ...
There is also a header-only library present in Boost that have neat tools to deal with floating point datatypes
#include <boost/math/special_functions/fpclassify.hpp>
You get the following functions:
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);
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.
There are three "official" ways: posix isnan macro, c++0x isnan 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
#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 );
}
Compiling with g++ (TDM-2 mingw32) 4.4.1:
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> _
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:
bool custom_isnan(double var)
{
volatile double d = var;
return d != d;
}
You can use numeric_limits<float>::quiet_NaN( ) defined in the limits standard library to test with. There's a separate constant defined for 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;
}
I don't know if this works on all platforms, as I only tested with g++ on Linux.
You can use the isnan() function, but you need to include the C math library.
#include <cmath>
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.
inline bool isnan(double x) {
return x != x;
}
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 check v != 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 the
Posix 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 returns false 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.
#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 ) );
}
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):
[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)]
> _
Results with Visual C++:
[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)]
> _
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.
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 prevention
My answer to this question is don't use retroactive checks for nan. Use preventive checks for divisions of the form 0.0/0.0 instead.
#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 results from the operation 0.f/0.f, or 0.0/0.0. nan is a terrible nemesis to the stability of your code that must be detected and prevented very carefully1. The properties of nan 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 see x != 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 for inf or -inf. (-inf < 0) returns TRUE, ( 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 be 0, basically. You may want 0.0/0.0 to generate HUGE instead. So,
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.
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 to nan doesn't mean you can be lazy and not check for 0.0/0.0 before it happens.
1 Checks for nan via x != 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).
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);
}
This works if sizeof(int) is 4 and sizeof(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.
A possible solution that would not depend on the specific IEEE representation for NaN used would be the following:
template<class T>
bool isnan( T f ) {
T _nan = (T)0.0/(T)0.0;
return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}
Considering that (x != x) is not always guaranteed for NaN (such as if using the -ffast-math option), I've been using:
#define IS_NAN(x) (((x) < 0) == ((x) >= 0))
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:
#define IS_NAN(x) (!((x)<0) && !((x)>=0)
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.
#ifndef isnan
#define isnan(a) (a != a)
#endif
This works:
#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;
}
output: isnan
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.
#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;
}
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 yield false 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:
static inline uint64_t load_ieee754_rep(double a) {
uint64_t r;
static_assert(sizeof r == sizeof a, "Unexpected sizes.");
std::memcpy(&r, &a, sizeof a); // Generates movq instruction.
return r;
}
static inline uint32_t load_ieee754_rep(float a) {
uint32_t r;
static_assert(sizeof r == sizeof a, "Unexpected sizes.");
std::memcpy(&r, &a, sizeof a); // Generates movd instruction.
return r;
}
constexpr uint64_t inf_double_shl1 = UINT64_C(0xffe0000000000000);
constexpr uint32_t inf_float_shl1 = UINT32_C(0xff000000);
// The shift left removes the sign bit. The exponent moves into the topmost bits,
// so that plain unsigned comparison is enough.
static inline bool isnan2(double a) { return load_ieee754_rep(a) << 1 > inf_double_shl1; }
static inline bool isinf2(double a) { return load_ieee754_rep(a) << 1 == inf_double_shl1; }
static inline bool isfinite2(double a) { return load_ieee754_rep(a) << 1 < inf_double_shl1; }
static inline bool isnan2(float a) { return load_ieee754_rep(a) << 1 > inf_float_shl1; }
static inline bool isinf2(float a) { return load_ieee754_rep(a) << 1 == inf_float_shl1; }
static inline bool isfinite2(float a) { return load_ieee754_rep(a) << 1 < inf_float_shl1; }
The std versions of isinf and isfinite load 2 double/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 and inf_float_shl1 constants get encoded as immediate operands into the assembly instructions.
Faster isnan2 is just 2 assembly instructions:
bool isnan2(double a) {
bool r;
asm(".intel_syntax noprefix"
"\n\t ucomisd %1, %1"
"\n\t setp %b0"
"\n\t .att_syntax prefix"
: "=g" (r)
: "x" (a)
: "cc"
);
return r;
}
Uses the fact that ucomisd instruction sets parity flag if any argument is NaN. This is how std::isnan works when no -ffast-math options is specified.
The IEEE standard says
when the exponent is all 1s
and
the mantissa is not zero,
the number is a NaN.
Double is 1 sign bit, 11 exponent bits and 52 mantissa bits.
Do a bit check.
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:
bool IsNan(float a)
{
char s[4];
sprintf(s, "%.3f", a);
if (s[0]=='n') return true;
else return false;
}
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")
This detects infinity and also NaN in Visual Studio by checking it is within double limits:
//#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;