Float or Double Special Value

2019-05-02 05:57发布

问题:

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?

回答1:

In Visual C++, there is a non-standard _isnan(double) function that you can import through float.h.

In C, there is a isnan(double) function that you can import through math.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.



回答2:

We have done that by using NaN:

double d = std::numeric_limits<double>::signaling_NaN();
bool isNaN = (d != d);

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 in math.h, which checks a floating point number for a NaN value too.



回答3:

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.



回答4:

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.