Violapterin
Violapterin

Reputation: 347

Does c++ std's inf behave exactly as common-sensical infinity

I was implementing a reasonably complicated numerical algorithm. It contains some exponentials, among which I discovered, upon printing the intermediate result, that there were some overflows of double. However, the terminal prints inf (not Inf or NaN), and it seems that it is not a double, not even the minimum or maximum expressible double. But it seems inf behaves as if it were the extended real number system (the perspective that positive and negative infinity be regarded as a true number, rather than an abbreviation of statement involving limits).

I have conducted a test: (g++ version: "Apple LLVM version 8.0.0 (clang-800.0.42.1)")

#include <iostream> // cout
#include <cmath> // exp, log
#include <limits> // data ranges

int main(void)
{
   const double dMin =std::numeric_limits<int>::min();
   const double dMax =std::numeric_limits<int>::max();
   double p1 =std::exp(710);
   double p2 =std::exp(750);
   double p3 =std::exp(800);
   double p4 =-std::log(0.0);
   std::cout << "p1 :=std::exp(710) =" << p1 << '\n';
   std::cout << "p2 :=std::exp(750) =" << p2 << '\n';
   std::cout << "p3 :=std::exp(800) =" << p3 << '\n';
   std::cout << "p4 :=-std::log(0.0) =" << p4 << '\n';
   std::cout << "does p1==dMax? " << ( (p1==dMax) ? "yes" : "no" ) << '\n';
   std::cout << "does p1==-dMin? " << ( (p1==-dMin) ? "yes" : "no" ) << '\n';
   std::cout << "does p1==p2? " << ( (p1==p2) ? "yes" : "no" ) << '\n';
   std::cout << "does p2==p3? " << ( (p2==p3) ? "yes" : "no" ) << '\n';
   std::cout << "does p3==p4? " << ( (p3==p4) ? "yes" : "no" ) << '\n';
   std::cout << "does 3*p1==p2/2+1? " << ( (3*p1==p2/2+1) ? "yes" : "no" ) << '\n';
   std::cout << "does (-p1)*(-p2)==p3*p3*p3? " << ( ((-p1)*(-p2)==p3*p3*p3) ? "yes" : "no" ) << '\n';
   std::cout << "does std::log(p2)==std::exp(p3)? " << ( (std::log(p2)==std::exp(p3)) ? "yes" : "no" ) << '\n';
}

Output:

p1 :=std::exp(710) =inf
p2 :=std::exp(750) =inf
p3 :=std::exp(800) =inf
p4 :=-std::log(0.0) =inf
does p1==dMax? no
does p1==-dMin? no
does p1==p2? yes
does p2==p3? yes
does p3==p4? yes
does 3*p1==p2/2+1? yes
does (-p1)*(-p2)==p3*p3*p3? yes
does std::log(p2)==std::exp(p3)? yes

It seems that inf does resemble our concept of infinity, but not equal to std's max and min.

Is it safe, then, to assume that inf works in the same manner as common-sensical infinity? May I rely on operations in the intermediate steps of my algorithm which involves inf, taking it to be true infinity, and only deal with its results in the end? Or if not, should I catch it? But how can I, since it is not the maximum or minimum double?

Upvotes: 1

Views: 2339

Answers (3)

Bathsheba
Bathsheba

Reputation: 234695

Restricting this answer to IEEE754 floating point, +Inf arises from a computation like 1.0 / 0.0, and -Inf arises from something like -1.0 / 0.0.

Another type, NaN (not a number) arises from 0.0 / 0.0.

Two floating point variables set to +Inf will compare true with each other, ditto -Inf. They represent different quantities to std::numeric_limits<double>::max(). +Inf is larger than all values except itself and NaN.

Note that two floating point variables set to NaN will not compare true with each other, or with anything else for that matter.

(For what it's worth, std::log(0.0) must return -Inf, rather than NaN). See http://en.cppreference.com/w/cpp/numeric/math/log

Upvotes: 3

Holt
Holt

Reputation: 37606

As already mentioned by the other answers, the behavior of floating point numbers is not well-defined by the standard, however it is pretty well defined by IEC-559/IEEE-754, and most implementation use this. The first thing to do would be to check if your implementation effectively uses it:

static_assert(std::numeric_limits<double>::is_iec559, "Stupid implementation!");

Once you passed that assertion, things get a lot easier! First, you can use the following utility function to obtain a true infinity (you do not need is_iec559 to be true for this to work actually... ):

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

Better, IEEE-754 has very well-defined rules for the behavior of infinity: http://steve.hollasch.net/cgindex/coding/ieeefloat.html#operations1, e.g. -inf * -inf = +inf, +inf + +inf = +Inf, and so on. Standard mathematical functions have also well-defined behavior with infinity, so you can rely on them too.

So if your implementation follows the IEEE standard, yes you can rely on intermediate operations on infinity and only check the final results.


1 This is not an official resource but as far as I know, it is correct.

Upvotes: 2

eerorika
eerorika

Reputation: 238331

Does c++ std's inf ...

The C++ standard doesn't specify any requirements for how infinity behaves - or that infinity can be represented by floating point numbers.

If your system uses floating point numbers that conform to a particular floating point standard, then that standard might specify the behaviour of infinities.

It seems that inf does resemble our concept of infinity, but not equal to std's max and min.

Indeed. numeric_limits::max() is defined to return the maximum finite value.

how [to catch infinity], since it is not the maximum or minimum double?

If by catch you mean that you wish to check whether a value is infinity, you can compare to numeric_limits::infinity(), or if you have C++11, then std::isinf() (which checks for both positive and negative infinity).

Upvotes: 2

Related Questions