1

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).

Mordachai
  • 9,412
  • 6
  • 60
  • 112
  • 12
    Doesn't NaN do that already? – Brendan Long Nov 08 '11 at 20:22
  • 1
    Yeah, NaN has exactly those properties. – James Brock Nov 08 '11 at 20:25
  • That's essentially my question: does NaN do that, and if so, how to access and test against it? EDIT: numeric_limits::quiet_NaN() sounds like what I'm looking for. But it's a little incomplete - as in, how to test for one, what are the rules around quiet_NaN vs. signaling_NaN, etc.. – Mordachai Nov 08 '11 at 20:26
  • 3
    However, NaN will have peculiar properties (x == x is false for x = NaN), and you need to give the proper flag to MSVC (/fp:strict) for it to keep the NaN where it could eliminate it (like in `0 * kMagicConstant`, where it could replace the result by `0`) – Alexandre C. Nov 08 '11 at 20:29
  • @AlexandreC. That's the sort of issues I was vaguely aware of and hoping for more information on. – Mordachai Nov 08 '11 at 20:34

4 Answers4

3

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

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • 2
    Just as an aside, comparing NaNs is further complicated by the fact that there are many, many possible representations of it, while by contrast every other floating point value has a unique binary representation (and `+0` and `-0` compare equal). – Kerrek SB Nov 08 '11 at 20:39
3

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();
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • @JamesBrock: Grand - I was just looking for that, but didn't find it in the previous standard. A sorely missed feature; great that's finally included! – Kerrek SB Nov 08 '11 at 20:36
2

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.

Wisdom's Wind
  • 1,448
  • 9
  • 10
2

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.]

Community
  • 1
  • 1
Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
  • Looking at the /fp documentation, it would appear that /fp:precise explicitly disables intrinsics and optimizations that could be false for IEEE special numbers (including X * 0 -> 0). So it would appear that /fp:precise (the default) is a good choice for VS 2010 – Mordachai Nov 08 '11 at 20:44