I have double (or float) variables that might be "empty", as in holding no valid value. How can I represent this condition with the built in types float and double?
One option would be a wrapper that has a float and a boolean, but that can´t work, as my libraries have containers that store doubles and not objects that behave as doubles. Another would be using NaN (std::numeric_limits). But I see no way to check for a variable being NaN.
How can I solve the problem of needing a "special" float value to mean something other than the number?
We have done that by using NaN:
NaN values compared for equality against itself will yield false. That's the way you test for NaN, but which seems to be only valid if
std::numeric_limits<double>::is_iec559
is true (if so, it conforms to ieee754 too).In C99 there is a macro called
isnan
for this inmath.h
, which checks a floating point number for a NaN value too.In Visual C++, there is a non-standard
_isnan(double)
function that you can import throughfloat.h
.In C, there is a
isnan(double)
function that you can import throughmath.h
.In C++, there is a isnan(double) function that you can import through
cmath
.As others have pointed out, using NaN's can be a lot of hassle. They are a special case that has to be dealt with like NULL pointers. The difference is that a NaN will not usually cause core dumps and application failures, but they are extremely hard to track down. If you decide to use NaN's, use them as little as possible. Overuse of NaN's is an offensive coding practice.
It's not a built-in type, but I generally use
boost::optional
for this kind of thing. If you absolutely can't use that, perhaps a pointer would do the trick -- if the pointer is NULL, then you know the result doesn't contain a valid value.One option would be a wrapper that has a float ad a boolean, but that can´t work, as my libraries have containers that store doubles and not objects that behave as doubles.
That's a shame. In C++ it's trivial to create a templated class that auto-converts to the actual double (reference) attribute. (Or a reference to any other type for that matter.) You just use the cast operator in a templated class. E.g.: operator TYPE & () { return value; } You can then use a HasValue<double>anywhere you'd normally use a double.
Another would be using NaN (std::numeric_limits). But i see no way to check for a variable being NaN.
As litb and James Schek also remarked, C99 provides us with isnan().
But be careful with that! Nan values make math & logic real interesting! You'd think a number couldn't be both NOT>=foo and NOT<=foo. But with NaN, it can.
There's a reason I keep a WARN-IF-NAN(X) macro in my toolbox. I've had some interesting problems arise in the past.