4

In the past we have been using Visual Studio's _fpclass to understand if an infinite was positive or negative: http://msdn.microsoft.com/en-us/library/aa246882%28v=vs.60%29.aspx

Passing to std::fpclassify, there's no distinction anymore between positive and negative infinite: http://en.cppreference.com/w/cpp/numeric/math/fpclassify

Can I safely check the sign of infinite with one of the methods here?
Is there a standard sign function (signum, sgn) in C/C++?

Note:

  • Independently if fastmath is enabled
  • In a portable way

Note 2:

  • C++11 is applicable
Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197

3 Answers3

6

For only checking the sign of an infinite value (as stated in the thread title), this code should suffice:

template<typename T>
typename std::enable_if<std::numeric_limits<T>::has_infinity, bool>::type Signed(T const& Value)
{
    return Value == -std::numeric_limits<T>::infinity();
}

Edit: If you have access to a C++11 ready compiler, there is also a function provided by the standard library, called std::signbit in the header <cmath>. It works for every fundamental floating point type and for every kind of value (so also for infinite and even for NaNs) and should therefore be a more general solution.

Fytch
  • 1,067
  • 1
  • 6
  • 18
1

You do not really need any special functions to detect infinities and NaNs:

double x = ...;
bool is_nan = x != x;
bool is_finite = !is_nan && x != 2 * x;
bool is_negative = !is_nan && x < 0;
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • +1. As numbers, `+inf` and `-inf` aren't particularly special. Most arithmetic on them won't produce `nan`s, and they compare like any other number. – Sneftel Sep 18 '14 at 10:06
  • The point is, `x != x` when fast math is enabled might return false! – Antonio Sep 18 '14 at 10:07
  • 1
    @Antonio Do not enable options that screw up you maths then. Fast but wrong is not a virtue. – Maxim Egorushkin Sep 18 '14 at 10:08
  • @Antonio If you expect NaNs, then you cannot use fast math. – Sneftel Sep 18 '14 at 10:14
  • 1
    This code is not portable, since `x != x` is no portable classification of NaN floats. The compiler isn't even forced to use the IEEE floating point standard. – Fytch Sep 18 '14 at 10:15
  • @Conclusio You are incorrect. C standard requires that a NaN always compares unequal to any other value, even the identical NaN. – Maxim Egorushkin Sep 18 '14 at 10:23
  • @MaximYegorushkin I found nothing in the C++ working draft neither at [expr.eq] nor at [basic.fundamental]. Could you please tell me where to find it? – Fytch Sep 18 '14 at 10:59
  • 1
    @MaximYegorushkin That's a “commentary” section in a book that is itself one person's commentary on the C and C++ standards. It is not written so rigorously that the sentence “A NaN always compares unequal to any other value, even the identical NaN” cannot be interpreted to have meant “A [IEEE-754] NaN always compares unequal to any other value, even the identical NaN”, since IEEE 754/IEC 60559 is the subject of the discussion in the previous sentences. Nothing here is binding for either C or C++ compilers, unless the compiler in question affirms its support for IEC 60559. – Pascal Cuoq Sep 18 '14 at 11:48
  • @PascalCuoq The author of that book knows what he talks about http://www.informit.com/authors/bio/86f640f5-f526-4915-b28b-62689c48f793 – Maxim Egorushkin Sep 18 '14 at 11:57
  • @MaximYegorushkin … which makes it even more conspicuous that the C standard does not say that `double` must have a `NaN` value or that such a value, if present, must compare different to itself. If Derek Jones wanted such a sentence to be present in the standard, he had the opportunity to try to try and slip it in there at the appropriate committee meetings. Therefore, it is a deliberate omission. The standard does not say that a NaN value must compare different to itself and that is on purpose. – Pascal Cuoq Sep 18 '14 at 12:01
  • The closest the C11 standard comes to saying that `NaN != NaN` is in clause 7.12.14 about comparison macros. But that section is really about the comparison macros, not `==`. – Pascal Cuoq Sep 18 '14 at 12:13
  • @PascalCuoq He states that the _terminology originates from IEC 60559 (or to be exact IEEE-754 and IEEE-854 standards that eventually became the ISO/IEC Standard)_. My guess is that C standard writers did not bother to copy another standard in its entirety and left it underspecified, not because they wanted NaN to compare equal to itself. And that explains his comment. – Maxim Egorushkin Sep 18 '14 at 12:14
0

You seem to already know that x is positive or negative infinity, you just don't know which. In that case, you'd use the same tactic you would if you knew x were 7 or -7 but didn't know which:

x > 0

There's nothing wrong with that. Of course x > 24 or comparison against any other finite value would work, since positive infinity is larger than all finite values and negative infinity is smaller than all finite values, but comparison with 0 seems like the most readable way to check for the sign.

If you're not sure whether x is infinity at all then test for it explicitly, as suggested in Fytch's answer:

if (x == std::numeric_limits<double>::infinity()) {
    // positive infinity
} else if (x == -std::numeric_limits<double>::infinity()) {
    // negative infinity
} else {
    // something else
}
Arthur Tacca
  • 8,833
  • 2
  • 31
  • 49