The primary and most reliable way to represent infinity in C++ is using the std::numeric_limits<T>::infinity() template function for floating-point types. Because standard integer types are fundamentally finite, they cannot represent a true infinity.
Representing infinity for floating-point types
The IEEE 754 standard for floating-point arithmetic includes special values for positive and negative infinity. C++ provides two main ways to access these values for float, double, and long double.
Method 1: Using std::numeric_limits (recommended)
This is the modern and type-safe approach that is part of the C++ Standard Library. It requires including the <limits> header.
-
**Positive infinity:**cpp
#include <iostream> #include <limits> int main() { // Assign positive infinity to a double variable double pos_inf = std::numeric_limits<double>::infinity(); std::cout << "Positive infinity (double): " << pos_inf << std::endl; // Assign positive infinity to a float variable float pos_inf_f = std::numeric_limits<float>::infinity(); std::cout << "Positive infinity (float): " << pos_inf_f << std::endl; }Use code with caution.
Output:``` Positive infinity (double): inf Positive infinity (float): inf
-
**Negative infinity:**You can get negative infinity by applying the unary negation operator to the positive infinity value.cpp
#include <iostream> #include <limits> int main() { double neg_inf = -std::numeric_limits<double>::infinity(); std::cout << "Negative infinity (double): " << neg_inf << std::endl; }Use code with caution.
Output:``` Negative infinity (double): -inf
-
**Checking for infinity:**You can check if a floating-point number is infinite using the
std::isinf()function from the<cmath>header.cpp#include <iostream> #include <cmath> #include <limits> int main() { double pos_inf = std::numeric_limits<double>::infinity(); double neg_inf = -std::numeric_limits<double>::infinity(); double not_inf = 5.0; std::cout << "Is " << pos_inf << " infinite? " << std::isinf(pos_inf) << std::endl; std::cout << "Is " << neg_inf << " infinite? " << std::isinf(neg_inf) << std::endl; std::cout << "Is " << not_inf << " infinite? " << std::isinf(not_inf) << std::endl; }Use code with caution.
Output:``` Is inf infinite? 1 Is -inf infinite? 1 Is 5 infinite? 0
Method 2: Using the INFINITY macro
The <cmath> header provides the INFINITY macro, which is a compile-time constant for positive infinity. Its type is float. While it is shorter to type, it is generally less type-safe than std::numeric_limits and may not be exported if you are using C++ modules.
#include <iostream>
#include <cmath>
int main() {
double pos_inf = INFINITY;
double neg_inf = -INFINITY;
std::cout << "Positive infinity (macro): " << pos_inf << std::endl;
std::cout << "Negative infinity (macro): " << neg_inf << std::endl;
}
Use code with caution.
Output:
Positive infinity (macro): inf
Negative infinity (macro): -inf
Implicit generation of infinity
On systems that follow the IEEE 754 standard, you can also generate an infinity value by performing a mathematical operation that results in one, such as dividing a positive, non-zero number by zero.
#include <iostream>
int main() {
double inf = 1.0 / 0.0;
double neg_inf = -1.0 / 0.0;
std::cout << "Infinity from division: " << inf << std::endl;
std::cout << "Negative infinity from division: " << neg_inf << std::endl;
}
Use code with caution.
Output:
Infinity from division: inf
Negative infinity from division: -inf
This is an implicit and often less clear way to obtain infinity, and an integer division by zero will typically cause a program crash (SIGFPE) instead of producing an infinite value.
Handling infinity for integer types
Since integer types like int, long, and long long have a finite range, there is no value that can truly represent infinity. This means that attempting to assign an "infinite" value to an integer will result in overflow or undefined behavior.
To simulate infinity for integers, you have two primary options, depending on your use case:
Option 1: Use the maximum value
A common and simple approach for many algorithms (like Dijkstra's algorithm for pathfinding) is to use the maximum possible value for the integer type. You can access this with std::numeric_limits<T>::max(), found in the <limits> header.
#include <iostream>
#include <limits>
int main() {
int max_int = std::numeric_limits<int>::max();
long long max_ll = std::numeric_limits<long long>::max();
std::cout << "Maximum integer value: " << max_int << std::endl;
std::cout << "Maximum long long value: " << max_ll << std::endl;
if (5000000000LL > max_int) {
std::cout << "A larger value is greater than max_int." << std::endl;
}
}
Use code with caution.
Output:
Maximum integer value: 2147483647
Maximum long long value: 9223372036854775807
A larger value is greater than max_int.
Important considerations for this approach:
- Arithmetic: Be extremely careful when performing arithmetic operations. Adding a positive number to
std::numeric_limits<int>::max()will cause an integer overflow, resulting in a very small negative number. - Comparison: Maximum value "infinity" works perfectly for comparisons, as it will always be greater than or equal to any other representable value of the same type.
Option 2: Create a wrapper class
For a more robust and semantically correct solution, you can create a custom class or std::variant (since C++17) that explicitly handles a state of "infinite". This provides true type safety and prevents unexpected arithmetic behavior.
#include <iostream>
class extended_int {
public:
// Enum to store the state: finite, positive infinity, or negative infinity
enum class State { FINITE, POS_INF, NEG_INF };
private:
State state;
long long value;
public:
// Constructor for finite integer values
extended_int(long long val) : state(State::FINITE), value(val) {}
// Default constructor for positive infinity
extended_int() : state(State::POS_INF), value(0) {}
// Method to create negative infinity
static extended_int neg_infinity() {
extended_int temp;
temp.state = State::NEG_INF;
return temp;
}
// Comparison operator overloading
bool operator<(const extended_int& other) const {
if (state == State::NEG_INF) return other.state != State::NEG_INF;
if (state == State::POS_INF) return false;
if (other.state == State::POS_INF) return true;
if (other.state == State::NEG_INF) return false;
return value < other.value;
}
// Example of a conversion to a string for printing
std::string to_string() const {
if (state == State::POS_INF) return "+inf";
if (state == State::NEG_INF) return "-inf";
return std::to_string(value);
}
};
int main() {
extended_int a = 100;
extended_int b = extended_int::neg_infinity();
extended_int c; // Defaults to positive infinity
std::cout << "a: " << a.to_string() << std::endl;
std::cout << "b: " << b.to_string() << std::endl;
std::cout << "c: " << c.to_string() << std::endl;
std::cout << "Is b < a? " << (b < a) << std::endl;
std::cout << "Is a < c? " << (a < c) << std::endl;
std::cout << "Is c < c? " << (c < c) << std::endl;
}
Use code with caution.
Output:
a: 100
b: -inf
c: +inf
Is b < a? 1
Is a < c? 1
Is c < c? 0
This wrapper provides precise control over behavior and is useful for complex algorithms where you need to manage a true concept of infinity alongside finite values.