Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using NaN in C++?

What's the best way to use NaNs in C++?

I found std::numeric_limits<double>::quiet_NaN() and std::numeric_limits<double>::signaling_NaN(). I'd like to use signaling_NaN to represent an uninitialized variable as follows:

double diameter = std::numeric_limits<double>::signaling_NaN(); 

This, however, signals (raises an exception) on assignment. I want it to raise an exception on use, not on assignment.

Is there any way to use signaling_NaN without raising an exception on assignment? Is there a good, portable alternative to signaling_NaN that will raise a floating point exception when used?

like image 950
Josh Kelley Avatar asked Oct 24 '08 21:10

Josh Kelley


People also ask

What is NaN in C?

NaN is unordered: it is not equal to, greater than, or less than anything, including itself. x == x is false if the value of x is NaN. You can use this to test whether a value is NaN or not, but the recommended way to test for NaN is with the isnan function (see Floating-Point Number Classification Functions).

What is NaN in double C?

Returns a quiet NaN (Not-A-Number) value of type double . The NaN values are used to identify undefined or non-representable values for floating-point elements, such as the square root of negative numbers or the result of 0/0.

Why NaN is used?

Unquoted literal constant NaN is a special value representing Not-a-Number. Since NaN always compares unequal to any number, including NaN, it is usually used to indicate an error condition for a function that should return a valid number. Note − Use the isNaN() global function to see if a value is an NaN value.

How do you represent NaN?

NaN stands for Not A Number and is one of the common ways to represent the missing value in the data. It is a special floating-point value and cannot be converted to any other type than float. NaN value is one of the major problems in Data Analysis.


2 Answers

What signaling NAN means is that when the CPU encounters it a signal is fired, (hence the name). If you want to detect uninitialized variables then raising the warning level on your compiler usually detects all paths that use uninitalized values. Failing that you can use a wrapper class that stores a boolean saying if the value is initialized:

template <class T> class initialized {     T t;     bool is_initialized; public:     initialized() : t(T()), is_initialized(false) { }     initialized(const T& tt) : t(tt), is_initialized(true) { }     T& operator=(const T& tt) { t = tt; is_initialized = true; return t; }     operator T&() {          if (!is_initialized)              throw std::exception("uninitialized");          return t;     } }; 
like image 40
Motti Avatar answered Sep 28 '22 03:09

Motti


After looking into this some more, it looks like signaling_NaN is useless as provided. If floating point exceptions are enabled, then calling it counts as processing a signaling NaN, so it immediately raises an exception. If floating point exceptions are disabled, then processing a signaling NaN automatically demotes it to a quiet NaN, so signaling_NaN doesn't work either way.

Menkboy's code works, but trying to use signaling NaNs runs into other problems: there's no portable way to enable or disable floating point exceptions (as alluded to here and here), and if you're relying on exceptions being enabled, third party code may disable them (as described here).

So it seems like Motti's solution is really the best choice.

like image 84
Josh Kelley Avatar answered Sep 28 '22 05:09

Josh Kelley