Draft 2002-07-18

<limits>

The <limits> header declares the numeric_limits class template and related types and specializations that define the limits and characteristics of the fundamental arithmetic types (such as largest possible int). It is the C++ equivalent of the C headers <cfloat> and <climits>.

The <limits> header has a number of advantages over the <cfloat> and <climits> declarations. In particular, by using a template, you can write your own template-based classes that depend on the characteristics of a template parameter; this is not possible with the macro-based C headers.

float_denorm_style type

Represent existence of denormalized floating point values

enum float_denorm_style {
  denorm_indeterminate = -1;
  denorm_absent = 0;
  denorm_present = 1;
};

The float_denorm_style type is an enumerated type that represents whether denormalized floating-point values are supported.

float_round_style type

Represent the floating-point rounding style

enum float_round_style {
  round_indeterminate = -1,
  round_toward_zero = 0,
  round_to_nearest = 1,
  round_toward_infinity = 2,
  round_toward_neg_infinity = 3
};

The float_round_style type is an enumerated type that represents how floating-point numbers are rounded.

numeric_limits class template

Represent the limits and characteristics of an arithmetic type

template<typename T>
class numeric_limits
{
public:
  static const bool is_specialized = false;
  static T min() throw();
  static T max() throw();
  static const int digits = 0;
  static const int digits10 = 0;
  static const bool is_signed = false;
  static const bool is_integer = false;
  static const bool is_exact = false;
  static const int radix = 0;
  static T epsilon() throw();
  static T round_error() throw();
  static const int min_exponent = 0;
  static const int min_exponent10 = 0;
  static const int max_exponent = 0;
  static const int max_exponent10 = 0;
  static const bool has_infinity = false;
  static const bool has_quiet_NaN = false;
  static const bool has_signaling_NaN = false;
  static const float_denorm_style has_denorm = denorm_absent;
  static const bool has_denorm_loss = false;
  static T infinity() throw();
  static T quiet_NaN() throw();
  static T signaling_NaN() throw();
  static T denorm_min() throw();
  static const bool is_iec559 = false;
  static const bool is_bounded = false;
  static const bool is_modulo = false;
  static const bool traps = false;
  static const bool tinyness_before = false;
  static const float_round_style round_style =
    round_toward_zero;
};

The numeric_limits class template represents the limits and characteristics of an arithmetic type. The members that are shown as static const are constants that you can use in other integral constant expressions.

The default is for all members to be 0 or false. The template has specializations for all fundamental types, and only for the fundamental types. Every specialization defines every member, even if the member does not pertain to the type (e.g., floating-point characteristics of an integral type). Meaningless members are defined as 0 or false.

For example, suppose you are writing a data analysis program. Among the data are points you want to ignore, but you need to keep their places in the data array. You decide to insert a special marker value. Ideally, the marker value is one that cannot possibly appear in the actual data stream, such as infinity. If the type does not support infinity, you decide to use the maximum finite value. Example 13-26 lists the no_data function, which returns the value used for the no-data marker.

Example 13-26: Using infinity or maximum finite value to mean "no data."

// Define a template that will differentiate types that
// have a specialized numeric_limits and an explicit
// value for infinity.
template<typename T, bool is_specialized, bool has_infinity>
struct max_or_infinity
{};

// Specialize the template to obtain the value of infinity.
template<typename T>
struct max_or_infinity<T, true, true>
{
  static T value()
    { return std::numeric_limits<T>::infinity(); }
};

// Specialize the template if infinity is not supported.
template<typename T>
struct max_or_infinity<T, true, false>
{
  static T value() { return std::numeric_limits<T>::max(); }
};

// Note that type without a numeric_limits specialization
// do not have a max_or_infinity specialization, so the
// no_data function would result in compile-time errors
// when applies to such a type.
//
// The no_data function returns a value that can be used
// to mark points that do not have valid data.
template<typename T>
T no_data()
{
  return max_or_infinity<T,
    std::numeric_limits<T>::is_specialized,
    std::numeric_limits<T>::has_infinity>::value();
}

If you write your own numeric type, say, a type for rational numbers, be sure to specialize numeric_limits<> for your type.

Following are descriptions of the members of numeric_limits:

static T denorm_min() throw()
The denorm_min function returns the smallest positive denormalized floating point value. If has_denorm is false, it returns the smallest positive normalized value. For non-floating point types, it returns zero.
static const int digits
The digits member is the number of radix digits that can be represented: for integer types, it is the number of non-sign digits, and for floating-point types, it is the number of digits in the mantissa.
static const int digits10
The digits10 member is the number of decimal digits that can be represented. If is_bounded is false, digits10 is zero.
static T epsilon() throw()
The epsilon function returns the difference between 1.0 and the smallest representable value greater than 1.0. For integral types, epsilon returns zero.
static const float_denorm_style has_denorm
The has_denorm member stores the denormalized floating point style. It is denorm_indeterminate if the style cannot be determined at compile time. It is meaningful for all floating point types.
static const bool has_denorm_loss
The has_denorm_loss member is true if the loss of accuracy in a floating-point computation is a denormalization loss instead of an inexect result.
static const bool has_infinity
The has_infinity member is true if the floating point type can represent positive infinity. In particular, this is true when is_iec559 is true.
static const bool has_quiet_NaN
The has_quiet_NaN member is true if the floating point type can represent a quiet (non-signaling) NaN (not-a-number). In particular, this is true when is_iec559 is true.
static const bool has_signaling_NaN
The has_signaling_NaN member is true if the floating point type can represent a signaling NaN (not-a-number). In particular, this is true when is_iec559 is true.
static T infinity() throw()
The infinity function returns the value of positive infinity if has_infinity is true.
static const bool is_bounded
The is_bounded member is true if the type represents a finite set of values. This is true for all fundamental types.
static const bool is_exact
The is_exact member is true if the type represents values exactly. It is true for all integral types and false for the fundamental floating-point types.
static const bool is_iec559
The is_iec559 member is true if the type follows the IEC 559 (IEEE 754) standard for floating point arithmetic. It is meaningful only for floating point types. Among the requirements of the IEC 559 standard are support for positive and negative infinity and values that are not-a-number (NaN).
static const bool is_integer
The is_integer member is true for all integral types.
static const bool is_modulo
The is_modulo member is true if the type uses modulo arithmetic. This is always true for unsigned integral types and usually true for signed integral types. It is false for typical floating point types.
static const bool is_signed
The is_signed member is true if the type is signed, that is, supports positive and negative values.
static const bool is_specialized
The is_specialized member is true for all specializations. It is false by default, so you can detect whether numeric_limits<> has been specialized for a particular type, and so you can determine whether a false or zero value is meaningful.
static T max() throw()
The max function returns the maximum finite value when is_bounded is true.
static const int max_exponent
The max_exponent member is the largest allowable exponent for a floating point number. In other words, radix raised to max_exponent - 1 is representable as a finite number, but radix raised to max_exponent is not.
static const int max_exponent10
The max_exponent10 member is the largest allowable decimal exponent for a floating point number. In other words, 10 raised to max_exponent10 - 1 is representable as a finite number, but 10 raised to max_exponent10 is not.
static T min() throw()
The min function returns the minimum finite value. It is meaningful when is_bounded is true or when is_bounded and is_signed are both false.
static const int min_ e xponent
The min_exponent member is the smallest allowable exponent for a floating point number such that radix raised to min_exponent - 1 is representable as a normalized floating-point number.
static const int min_exponent10
The min_exponent10 member is the smallest negative decimal exponent such that 10 raised to min_exponent10 is representable as a normalized floating point number.
static T quiet_NaN() throw()
The quiet_NaN function returns a quiet NaN value if has_quiet_NaN is true.
static const int radix
The radix member is the base used in the representation. For floating point numbers, it is the base of the exponent.
static T round_ erro r() throw()
The round_error function returns the maximum rounding error.
static const float_round_style round_style
The round_style member is the rounding style used by the floating point type. For integral types, the value is always round_toward_zero.
static T signaling_NaN() throw()
The signaling_NaN function returns a signaling NaN value if has_signaling_NaN is true.
static const bool tinyness_before
The tinyness_before member is true if a floating point type tests for denormalized values before rounding.
static const bool traps
The traps member is true if arithmetic errors result in signals or exceptions. It is false if errors are quietly ignored.

The numeric_limits template is specialized for all the fundamental numeric types. In each case, is_specialized is true, and other members are set as appropriate. No other types in the C++ standard have numeric_limits specializations.