1.17 Numerical Limits and Number Classification

When working with C's various numeric types, it's important to understand the range of values that each type can hold.

1.17.1 Value Ranges of Integer Types

The value ranges of the integer types are documented in the header file limits.h. The constants, listed in Table 1-25, indicate the largest and smallest values that can be represented by the given type.

Table 1-25. Limits of the integer types

Type

Minimum

Maximum

Maximum of the unsigned type

char
CHAR_MIN
CHAR_MAX
UCHAR_MAX
signed char
SCHAR_MIN
SCHAR_MAX

 

short
SHRT_MIN
SHRT_MAX
USHRT_MAX
int
INT_MIN
INT_MAX
UINT_MAX
long
LONG_MIN
LONG_MAX
ULONG_MAX
long long(*)
LLONG_MIN(*)
LLONG_MAX(*)
ULLONG_MAX(*)

If char is interpreted as signed, then CHAR_MIN is equal to SCHAR_MIN and CHAR_MAX is equal to SCHAR_MAX. If not, then CHAR_MIN is equal to 0 and CHAR_MAX is equal to UCHAR_MAX.

In addition to the constants listed in Table 1-25, limits.h also contains the following:

CHAR_BIT

The number of bits in a byte (usually 8)

MB_LEN_MAX

The maximum number of bytes in a multibyte character

In the header file stdint.h(*), constants are also defined to document the minimum and maximum values of the types wchar_t, wint_t, size_t, ptrdiff_t, and sig_atomic_t, and of the fixed-width integer types, such as int_least32_t. The names of these constants are formed from the type names as follows: the type name is written all in capital letters, and the suffix _t is replaced by _MIN or _MAX. For example:

WCHAR_MIN         // Minimum value of wchar_t
INT_LEAST32_MAX   // Maximum value of int_least32_t

For the unsigned types only the ..._MAX constants are defined.

1.17.2 Range and Precision of Real Floating Types

The macros listed in Table 1-26 are defined in the header file float.h to represent the range and the precision of the types float, double, and long double. The macro names are formed using the prefixes FLT for float, DBL for double, and LDBL for long double. The macros FLT_RADIX and FLT_ROUNDS apply to all three floating types.

Table 1-26. Macros for floating types in float.h

Macro name

Purpose

FLT_RADIX

Base (or radix) of the exponential notation

FLT_ROUNDS

Indicates how rounding is performed on values that cannot be represented exactly:

-1 = undetermined

0 = towards zero,

1 = towards the nearest representable value

2 = upwards

3 = downwards

FLT_MANT_DIG 
DBL_MANT_DIG 
LDBL_MANT_DIG

The number of digits in the mantissa to base FLT_RADIX

FLT_MIN_EXP 
DBL_MIN_EXP 
LDBL_MIN_EXP

Minimum value of the exponent to base FLT_RADIX

FLT_MAX_EXP 
DBL_MAX_EXP 
LDBL_MAX_EXP

Maximum value of the exponent to base FLT_RADIX

The macros listed in Table 1-26 document the range and precision of all real floating types. In actual programs, such information is most often needed for decimal (base 10) notation. Accordingly, you can use the macros for type float listed Table 1-27, and which are defined in float.h.

Table 1-27. Limits for the type float

Macro name

Purpose

FLT_DIG

Precision as a number of decimal digits

FLT_MIN_10_EXP

Minimum negative exponent to base 10

FLT_MAX_10_EXP

Maximum positive exponent to base 10

FLT_MIN

Minimum representable positive floating-point number

FLT_MAX

Maximum representable floating-point number

FLT_EPSILON

Minimum positive representable floating-point number x such that 1.0 + x != 1.0

Similar constants are also defined for the types double and long double. These have names beginning with DBL or LDBL in place of FLT.

ANSI C99 also introduces the macro DECIMAL_DIG, which indicates the precision of the largest floating type as a number of decimal digits.

1.17.3 Classification of Floating-Point Numbers

ANSI C99 defines five categories of floating-point numbers, listed in Table 1-28. A symbolic constant for each category is defined in the header file math.h.

Table 1-28. Floating-point categories

Macro name

Category

FP_ZERO

Floating-point numbers with the value 0

FP_NORMAL

Floating-point numbers in normalized representation

FP_SUBNORMAL[1]

[1] Tiny numbers may be represented in subnormal notation.

Floating-point numbers in subnormal representation

FP_INFINITE

Floating-point numbers that represent an infinite value

FP_NAN

Not a Number (NAN): bit patterns that do not represent a valid floating-point number

[1] Tiny numbers may be represented in subnormal notation.

The macros in Table 1-29 can be used to classify a real floating-point number x with respect to the categories in Table 1-28 without causing an error condition.

Table 1-29. Macros for floating-point number classification

Macro

Result

fpclassify(x)

Returns one of the constants described in Table 1-28 to indicate the category to which x belongs.

isfinite(x)

Returns "true" (i. e., a value other than 0) if the value of x is finite (0, normal, subnormal, not infinite, or NAN), otherwise 0.

isinf(x)

Returns "true" if x is an infinity, otherwise 0.

isnormal(x)

Returns "true" if the value of x is a normalized floating-point number not equal to 0. Returns 0 in all other cases.

isnan(x)

Returns "true" if x is "not a number" (NaN), otherwise 0.

signbit(x)

Returns "true" if x is negative (i. e., if the sign bit is set), otherwise 0

The following constants are also defined in math.h:

INFINITY

The maximum positive value of type float, used to represent infinity.

NAN (Not a Number)

A value of type float which is not a valid floating-point number.

NANs can be either quiet or signaling. If a signaling NAN occurs in the evaluation of an arithmetic expression, the exception status flag FE_INVALID in the floating point environment is set. This flag is not set when a quiet NAN occurs.

C implementations are not required to support the concept of NANs. If NANs are not supported, the constant NAN is not defined.