Mordachai
Mordachai

Reputation: 9662

Is there a double value which will remain itself despite any computation applied to it?

On the Windows XP..7 platforms, for x86 instruction sets, using standard C++ or a Microsoft compiler, is there a value I can assign a double which, when other computations are applied to it, will always result in that same value?

e.g.

const double kMagicValue = ???;
double x = kMagicValue;
cout << x * 9.1; // still outputs kMagicValue

As I understand it, there is a floating point error condition that once trigged, the remainder of all floating point computations will result in NAN or something similar...

I ask because I have a series of functions that try to compute a double for a given input, and for some inputs, "no answer (NAN)" is a good output (conceptually).

And I want to be able to be lazy, and string together computations that should, if any part results in NAN, result as a whole in NAN (i.e. kMagicValue).

Upvotes: 1

Views: 239

Answers (4)

Alexandre C.
Alexandre C.

Reputation: 56976

You shouldn't rely on NaN to do the job. It will always compare false to any value, including itself, and you have to make sure that the platform respects IEEE754 semantics to a certain extent (this includes having a NaN in the first place).

See horror stories there: Negative NaN is not a NaN?

If you really want this approach, and you are confident enough about IEEE754 support, be sure to compile with /fp:precise (since you use MSVC) so that the compiler doesn't optimize away stuff like 0 * NaN. Be aware that this might impact performance.

To get a NaN,

std::numeric_limits<double>::quiet_NaN()

To test for NaN

inline bool is_NaN(double x) { return !(x == x); }

But this approach is probably more trouble than it is worth. I'd rather use exceptions for control flow here.

The right thing to use is boost::optional<double>, but it can be a little verbose at some places

[Also, the Haskell language has first-class support for these kind of control flow, if C++ is not a must-go option, Maybe you can give it a try.]

Upvotes: 2

Kerrek SB
Kerrek SB

Reputation: 477368

Any floating point operation involving NaN results in NaN again (to my knowledge). Moreover, NaN compares unequal to itself, and it is unique among IEEE754 floats with this property. So, to test for it:

bool is_nan(double x) { return x != x; }

If you have C++11 support, you can use std::isnan(x) != 0 or std::fpclassify(x) == std::FP_NAN from <cmath> instead [thanks @James Brock].

To make it:

double make_nan() {
  assert(std::numeric_limits<double>::has_quiet_NaN);
  return std::numeric_limits<double>::quiet_NaN();
}

Upvotes: 3

Wisdom&#39;s Wind
Wisdom&#39;s Wind

Reputation: 1448

Actually there is a special floating point value named Not-A-Number (NaN). Any expression with NaN involved will return NaN.

#include <limits>
numeric_limits<double>::quiet_NaN()

Infinity not always remains the same. For example it become NaN if you try to divide on Infinity.

Upvotes: 2

Xeo
Xeo

Reputation: 131829

Quiet NaN should do just fine. You can get it from std::numeric_limits<double>::quiet_NaN() by including the <limits> header. There's also a signaling NaN, but using it will usually result in an exception.

Remember however, that you can't simple use mydouble == qNaN, since NaN compares equal to nothing, not even itself. You have to use that property of NaN to test it: bool isNaN = mydouble != mydouble;.

Upvotes: 3

Related Questions