Treatment of NaN

Hi guys,

suppose I have a division between double variables somewhere in my code.
If this division leads to an overflow, the result will be stored as "NaN", am I right?

Can I, in the following, check whether the resulting double is == NaN in order to see whether something went wrong?
Is this an efficient method?

Are there other cases in floating point calculations where you receive NaN as a result?


Best,

PiF

An "overflow" would probably be represented as either positive or negative infinity. NaN is literally "not a number".

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <cmath>

int main() {
    double a = 0, b = 0;

    double c = a / b;  // 0.0 / 0.0
    
    if (std::isnan(c)) std::cout << "c is NaN\n";
    
    // another way to check for NaN
    if (c != c) std::cout << "c does not equal itself!\n";

    a = 1.0;
    
    c = a / b;  // 1.0 / 0.0

    if (std::isnan(c)) std::cout << "\nc is NaN\n";
    else               std::cout << "\nc is not a NaN\n";

    if (std::isinf(c)) std::cout << "c is infinite\n";
}

c is NaN
c does not equal itself!

c is not a NaN
c is infinite

https://en.cppreference.com/w/c/numeric/math
https://en.cppreference.com/w/c/numeric/math/nan
https://en.wikipedia.org/wiki/NaN#Operations_generating_NaN
Last edited on
If this division leads to an overflow, the result will be stored as "NaN", am I right?

In that case, you would get some kind of infinity. +/- inf is distinct from NaN.

Are there other cases in floating point calculations where you receive NaN as a result?

Yes. NaNs occur generally when computing some indeterminate expression (e.g., dividing zero by +/- inf).
https://en.wikipedia.org/wiki/NaN#Operations_generating_NaN

Can I, in the following, check whether the resulting double is == NaN in order to see whether something went wrong?
No: assuming IEEE754, NaNs never compare equal with anything, even other NaNs. For instance, given a floating point value x, the expression x != x is false unless x is any NaN.

Generally prefer std::isnan() to test for NaN. This avoids unwanted side-effects in the floating point environment, if access to it is enabled.

The floating-point environment is a thread-local state-space. Its status flags control the current rounding behavior and track floating-point exceptions. For example, if an overflow occurs, an exception flag is set indicating an overflow occurred. Some operations on NaNs can set exception flags, possibly including self-comparison - but not std::isnan().

It's possible to access the floating point environment if you've said
#pragma STDC FENV_ACCESS ON
in your program. Explicitly opting-in allows the compiler to bother with it only when necessary.
Thanks guys! So what I am looking for is "inf" not "NaN".

Depending on some random parameters, I might get a division of a number by zero at one point in my code. It is either a division by the actual zero or by a number that is so small that the division leads to an overflow.

In both cases, I would get an inf, right?
Then it's no problem, because in a case like this, the code is simply supposed to do something else. I can use an if structure with "std::isinf(c)" as in @dutch's post.
Depending on some random parameters, I might get a division of a number by zero at one point in my code. It is either a division by the actual zero or by a number that is so small that the division leads to an overflow.



Just my 2 cents worth ….. Shouldn't you always be checking for this before you do division, as opposed to checking for inf or NaN afterwards?


Also, you may have numbers of sufficient smallness in the denominator, or largeness in the numerator that it produces an answer that is too large / small for your application never mind overflow, underflow, inf , or NaN.
I would suggest to use std::isnormal(...) with an assert since all not normal values are certainly unwanted and rather a bug.
Topic archived. No new replies allowed.