numeric_limits class template — Represents 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 data 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 header has specializations for
all fundamental types, and only for the fundamental types. Every
specialization in the standard library 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
.
You can specialize numeric_limits
for your own types. For
example, suppose you write a class, bigint
, to represent integers of arbitrary
size. You can define your specialization to show that the type is
unbounded, signed, integral, etc. You should follow the convention
of the standard library, namely, by defining all members, even if
they do not apply to your type. Be sure to define is_specialized
as true
.
Use numeric_limits
to query
the properties or traits of a numeric type. 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 (such as infinity) cannot possibly appear in the actual data
stream. If the floating-point type that you are using does not
support infinity, you can use the maximum finite value. Example 13-23 lists the
no_data
function, which returns
the value used for the no-data marker.
Example 13-23. 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 a type without a numeric_limits specialization does not have a
// max_or_infinity specialization, so the no_data function would result in
// compile-time errors when applied 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>
Tno_data( )
{
return max_or_infinity<T,
std::numeric_limits<T>::is_specialized,
std::numeric_limits<T>::has_infinity>::value( );
}
The C++ standard mandates that all integers are binary and use
two's complement, ones' complement, or signed magnitude
representation. The representation of floating-point numbers is not
specified. The numeric_limits
template assumes that a number is represented as a sign, a
significand (sometimes called the mantissa), a
base, and an exponent:
x = sign × significand × base
exponent |
In everyday arithmetic, we are used to working with a base of 10. (The base is also called the radix.) The most common bases for computer arithmetic, however, are 16 and 2. Many modern workstations use the IEC 60559 (IEEE 754) standard for floating-point arithmetic, which uses a base of 2.
The significand is a string of digits in the given base. There is an implied radix point at the start of the significand, so the value of the significand is always less than one. (A radix point is the generalization of a decimal point for any radix.)
A finite floating-point value is
normalized if the first digit of its
significand is nonzero, or if the entire value is 0
. The term
denormalized means a finite value is not
normalized.
The precision of a floating-point type is the maximum number of places in the significand. The range of a floating-point type depends primarily on the minimum and maximum values for the exponent.
The following are descriptions of the members of numeric_limits
:
static T
denorm_min
( )
throw( )
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 0
.
static
const
int
digits
The number of radix
digits that can be represented. For integer types, it is the
number of non-sign bits; for floating-point types, it is the
number of places in the significand.
static
const
int
digits10
The number of decimal digits that can be represented. If
is_bounded
is false
, digits10
is 0
.
static T
epsilon
( )
throw( )
Returns the difference between 1.0 and the smallest
representable value greater than 1.0. For integral types,
epsilon
returns 0
.
static const
float_denorm_style
has_denorm
Indicates 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
Indicates whether the loss of accuracy in a floating-point computation is a denormalization loss rather than an inexact result.
static
const
bool
has_infinity
Indicates whether the floating-point type can represent
positive infinity. In particular, has_infinity
is true
when is_iec559
is true
.
static
const
bool
has_quiet_NaN
Indicates whether the floating-point type can represent
a quiet (nonsignaling) NaN (not-a-number). In particular, this
is true
when is_iec559
is true
.
static
const
bool
has_signaling_NaN
Indicates whether the floating point type can represent
a signaling NaN. In particular, this is true
when is_iec559
is true
.
static
T
infinity
( )
throw( )
Returns the value of positive infinity if has_infinity
is true
.
static
const
bool
is_bounded
Indicates whether the type represents a finite set of
values. This is true
for
all fundamental types.
static
const
bool
is_exact
Indicates whether 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
Indicates whether the type follows the IEC 60559 (IEEE 754) standard for floating-point arithmetic. It is meaningful only for floating-point types. Among the requirements of the IEC 60559 standard are support for positive and negative infinity, and for values that are NaN.
static
const
bool
is_integer
true
for all integral
types.
static
const
bool
is_modulo
Indicates whether the type uses modulo arithmetic. This
is always true
for unsigned
integral types and often true
for signed integral types. It
is false
for typical
floating-point types.
static
const
bool
is_signed
Indicates whether the type is signed, that is, supports positive and negative values.
static
const
bool
is_specialized
Indicates whether numeric_limits
is specialized for
the type. It is false
by
default, so you can detect whether numeric_limits<>
has been
specialized for a particular type, and therefore determine
whether a false
or 0
value is meaningful.
static T
max
( )
throw( )
Returns the maximum finite value when is_bounded
is true
.
static
const
int
max_exponent
The largest allowable exponent for a finite floating-point number.
static
const
int
max_exponent10
The largest allowable decimal exponent for a finite floating-point number.
static T
min
( )
throw( )
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_exponent
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 smallest negative decimal exponent such that 10
raised to min_exponent10
is
representable as a normalized floating-point number.
static T
quiet_NaN
( )
throw( )
Returns a quiet NaN value if has_quiet_NaN
is true
.
static const int
radix
The base used in the representation of a numeric value. For floating-point numbers, it is the base of the exponent.
static T
round_error
( )
throw( )
Returns the maximum rounding error.
static const
float_round_style
round_style
Indicates the rounding style used by the floating-point
type. (See the float_round_style
type for a
definition of the possible return values.) For integral types,
the return value is always round_toward_zero
.
static T
signaling_NaN
( )
throw( )
Returns a signaling NaN value if has_signaling_NaN
is true
.
static const bool
tinyness_before
Indicates whether a floating-point type tests for denormalized values before rounding.
static const bool
traps
Indicates whether arithmetic errors
trap, that is, 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 and for no
other types in the C++ standard. In each case, is_specialized
is true
, and other members are set as
appropriate. The C++ standard (by way of the C standard) defines the
minimum requirements for an implementation. The requirements for
integral types are given in <climits>
, and for floating-point
types in <cfloat>
.
The following are the standard specializations: