1.#INF, 1.#IND and #QNAN floating point numbers and errors

By , last updated August 5, 2019

Floating point conditions

When programming, there are certain error condition that might arise from your code. If the compiler catches any compilation errors, it will stop compilation and tell you what and where the error is. The compiler also may issue a warning for certain constructs, which may or may not give you problems during runtime.

Here are some floating point conditions that you as a programmer should be aware of when doing floating point arithmetic (any of addition, subtraction, multiplication, and division), namely INF, IND, and NaN (QNAN and SNAN) conditions and errors.

Positive Negative Meaning
1.#INF -1.#INF Infinity
1.#SNAN -1.#SNAN Signalling NaN
1.#QNAN -1.#QNAN Quiet NaN
1.#IND -1.#IND Indefinite / Indeterminite NaN

The floating point specification is called IEEE 754-2008, and is behind a paywall. However, the Wikipedia page is quite detailed.

Read also: How to check for NAN / INF / IND in C++

#NaN value

C++ NaN stands for not a number. It is a value that depicts an undefined or unspecified value with floating point. The concept of NaN was introduced in 1985 by the IEEE 754 floating-point standard in which the concept of infinities was also given.

Here is an example of what NaN values can cause in a real video game: black dots.

#QNaN and #SNaN

There are two kinds of NaNs, quiet and signalling. Both are very similar, and in most instances they are identical. With MSVC, the signalling NaNs (sNaN) are by default quiet NaNs. They won’t raise any hardware exceptions (as all floating point exceptions are) and you won’t notice anything wrong until the printouts contain nothing but 1.#QNAN and the simulation fails miserably.

#INF value

C++ INF denotes “infinity”. Due to the finite nature of floating point numbers (32-bit for floats, 64-bit for doubles), infinite is represented by a finite value.

This type of error condition / value arises when the resultant number is overflowing or underflowing the capacity of the floating point number. In other words, the value is too large or too small to be represented as a floating point value.

So the value appears as #INF.

  • 1.#INF – if the result is a too large positive number.
  • -1.#INF – if the result is a too large negative number.

The easiest way to use get an infinite number is asking for it.

#include <limits>

// Infinite
auto positive_inf = std::numeric_limits<double>::infinity();
auto negative_inf = positive_inf * -1;

std::cout << "Positive infinity: " << positive_inf << std::endl;
std::cout << "Negative infinity: " << negative_inf << std::endl;

// Output
// Positive infinity: 1.#INF
// Negative infinity: -1.#INF

// Or division by zero
double zero = 0.0;
double divbyzero = 1.0 / zero;

// Output
// Division by zero: 1.#INF

Any operation with infinity gives another infinite value, so it behaves like a plague, and it’ll kill simulations where it can propagate to complete data sets within iterations.

std::cout << "Add: " << add << " Sub: " << sub << " Mul: " << mul << " Div: " << div << std::endl;

// Output:
// Add: 1.#INF Sub: 1.#INF Mul: 1.#INF Div: 1.#INF

When doing stream formatting, the infinity number might be mangled and may show something not expected.

#include <iomanip>

// Formatting (scientific)
for(size_t i=0; i<10; i++)
{
	std::cout << "Precision: " << std::scientific << i << std::setprecision(i) << " inf: " << positive_inf << std::endl;
}

// Output
// Precision: 0 inf: 1.#INF00e+000
// Precision: 1 inf: 1.$e+000
// Precision: 2 inf: 1.#Je+000
// Precision: 3 inf: 1.#IOe+000
// Precision: 4 inf: 1.#INFe+000
// Precision: 5 inf: 1.#INF0e+000
// Precision: 6 inf: 1.#INF00e+000
// Precision: 7 inf: 1.#INF000e+000
// Precision: 8 inf: 1.#INF0000e+000
// Precision: 9 inf: 1.#INF00000e+000

// Formatting (fixed)
for (size_t i=0; i<10; i++)
{
	std::cout << "Precision: " << std::fixed << i << std::setprecision(i) << " inf: " << positive_inf << std::endl;
}

// Output
// Precision: 0 inf: 1
// Precision: 1 inf: 1.$
// Precision: 2 inf: 1.#J
// Precision: 3 inf: 1.#IO
// Precision: 4 inf: 1.#INF
// Precision: 5 inf: 1.#INF0
// Precision: 6 inf: 1.#INF00
// Precision: 7 inf: 1.#INF000
// Precision: 8 inf: 1.#INF0000
// Precision: 9 inf: 1.#INF00000

Fixed notation with precision 0 is very dangerous! There is no indication this is an infinite number!

#IND

C++ #IND is a special kind of NaN, when the result can’t be determined. This is particular true for mathematical methods where certain inputs are undefined (acos, sqrt, and friends).

For instance, zero divided by zero (0.0 / 0.0) is undefined in the field of mathematics or #IND. It’s the same with floating points, it produced an indefinite and indeterminate number.

double a = 0.0;
double b = 0.0 / a;
double negative_sqrt = sqrt(-1);

std::cout << "0.0/0.0 = " << b << std::endl;
std::cout << "sqrt(-1) = " << negative_sqrt << std::endl;

// Output
// 0.0/0.0 = -1.#IND
// sqrt(-1) = -1.#IND

Capturing errors

There are a couple of ways to trap NANs, and some requires a debugger attached to get the best results.

Method 1: Comparison.

When comparing the variable against itself, it will produce opposite results than with normal numbers.

double inf = std::numeric_limits<double>::infinity();
double nan = std::numeric_limits<double>::quiet_NaN();
double ind = sqrt(-1);

if (nan != nan)
	std::cout << "nan != nan" << std::endl;

if (ind != ind)
	std::cout << "ind != ind" << std::endl;

if (inf != inf)
	std::cout << "inf != inf" << std::endl;

// Output
// nan != nan
// ind != ind
// std::isnan(nan) is true
// std::isnan(ind) is true

Note, infinity is a number!

Method 2 (C++11): Use the standard.

C++11 introduced a couple of methods to determine if a value is a NaN or not, which are residing the the std:: namespace.

// Method 2, std::isnan

if (std::isnan(nan))
    std::cout << "std::isnan(nan) is true" << std::endl;

if (std::isnan(ind))
    std::cout << "std::isnan(ind) is true" << std::endl;

if (std::isnan(inf))
    std::cout << "std::isnan(inf) is true" << std::endl;

// Output
// std::isnan(nan) is true
// std::isnan(ind) is true

Note that inf is still missing, which is correct behavior.

Method 3 (MSVC): Control floating-point control word.

The use of _controlfp and _control87 family will alter the floating-point control word, essentially making the computer issue a hardware exception when a floating point exception occurs. The default with MSVC is to silence floating point exceptions, with the possibility to silently destroy simulations.

I personally recommend turning on all floating point exceptions, so all (or most) cases can be reviewed and the code made more robust.

The usage is a bit counter-intuitive, but after a while you’ll get used to it. Here is what works for me.

// According to the docs, always clear fp control word
auto state = _clearfp();
state = _control87(0,0);

This will reset, and get current floating point control word state.

With this, we can modify the floating point control word to our liking.

// This will turn ON FPE for zerodiv
state = _control87(state & ~_EM_ZERODIVIDE, _MCW_EM);

// This WILL NOT fail
const double sqrtneg = sqrt(-1);

// This WILL fail due to zerodiv
const double zero = 0.0;
const double zerodivresult = 1.0 / zero;

838

Otherwise, we can break on indeterminate (#IND) with _EM_INVALID.

// This will turn on FPE for #IND
state = _control87(state & ~_EM_INVALID, _MCW_EM);

// This WILL fail
const double sqrtneg = sqrt(-1);

// This WILL NOT fail and it'll produce #inf
const double zero = 0.0;
const double zerodivresult = 1.0 / zero;

392

If you want to turn on two or more FPEs, you must do some bit arithmetic to set the right switches.

// This will turn on FPE for #IND and zerodiv
state = _control87(state & ~(_EM_ZERODIVIDE|_EM_INVALID), _MCW_EM);

If you want to turn all FPEs, this will do it.

// All FPEs
state = _control87(state & ~(_EM_INEXACT|_EM_UNDERFLOW
    |_EM_OVERFLOW|_EM_ZERODIVIDE|
    _EM_INVALID|_EM_DENORMAL), _MCW_EM);

To find out what floating point exception which are active, this snippet will help.

bool inexact	= 0 == (state & _EM_INEXACT);
bool underflow	= 0 == (state & _EM_UNDERFLOW);
bool overflow	= 0 == (state & _EM_OVERFLOW);
bool zerodiv	= 0 == (state & _EM_ZERODIVIDE);
bool invalid	= 0 == (state & _EM_INVALID);
bool denorm		= 0 == (state & _EM_DENORMAL);

std::cout << std::boolalpha << "Will break on: n"
    << "Inexact: " << inexact << "n"
    << "Underflow: " << underflow << "n"
    << "Overflow: " << overflow << "n"
    << "Zerodiv: " << zerodiv << "n"
    << "Invalid: " << invalid << "n"
    << "Denormal: " << denorm << "n";

// Output
// Will break on:
// Inexact: false
// Underflow: false
// Overflow: false
// Zerodiv: true
// Invalid: true
// Denormal: false

PS: Most of the printouts in this post is specific to Visual Studio. GCC will print out a simple nan or inf.

Professional Software Developer, doing mostly C++. Connect with Kent on Twitter.