BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlb_float

Detailed Description

Outline

Purpose

Provide floating-point classification types and functions.

Classes

Description

This component defines a utility struct, bdlb::Float, that provides functions analogous to C99 <math.h> library macros such as isinf and isnan that return whether a float or double value is infinite or not-a-number, respectively. These macros are not available in C++98 and so are provided as functions in this component.

Classification of Floating-Point Numbers

Floating-point numbers are used to represent a subset of the set of real numbers. The C++ float and double types are used to hold floating-point numbers, with float having (much) less precision than double. Floating point numbers can be classified into the following disjoint sets:

Zero positive and negative zero
Normal full-precision, non-zero, normal numbers
Subnormal reduced-precision numbers with small absolute values
Infinity positive and negative infinities
NaN not a number

A NaN value can be further classified into two disjoint subsets:

Signaling NaN invalid values that raises a signal in computations
Quiet NaN indeterminate values that propagate through computations

Note that not all platforms support signaling NaNs and that even those that do often require a specific action to enable signals on floating-point traps. Signaling NaNs are never the result of a normal floating-point operation. They are most often used as sentinels to detect the use of a value that has not yet been computed.

Quiet NaNs are the result of certain operations where the result is not defined mathematically. If an expression that results in a (quiet) NaN is used in a subsequent computation, the result is usually also a (quiet) NaN.

On platforms that implement the IEEE 754 standard for floating-point arithmetic, the following conditions result in non-normal floating-point values. In the following table, "NaN" always refers to a quiet NaN:

Condition Result
------------------- -----------------
Overflow Infinity
Underflow Subnormal or Zero
Normal / Infinity Zero
Infinity * Infinity Infinity
nonzero / Zero Infinity
Infinity + Infinity Infinity
Zero / Zero NaN
Infinity - Infinity NaN
Infinity / Infinity NaN
Infinity * Zero NaN

Note that the operations that result in Infinity follow the normal rules for sign propagation, e.g., -5.0 / 0.0 results in negative Infinity.

Future Enhancements

At present, this component works with float and double numbers. In the future, it will also work with long double. Note that casting a long double to double before applying these classification functions will not always yield correct results. For example, a large long double may get demoted to an infinite double. Similarly, a small long double may get demoted to a subnormal or zero double.

Thread Safety

Any of the functions in this component may safely be called simultaneously from multiple threads, even with the same arguments.

Usage

This section illustrates intended use of this component.

Example 1: Basic Syntax

On platforms that implement the IEEE 754 standard for floating-point arithmetic, dividing a positive number by zero yields positive infinity and dividing a negative number by zero yields negative infinity. The result of division by zero will therefore be detected as infinite by the isInfinite method and classified as infinity by the classify and classifyFine methods in this component:

double zero = 0.0;
double a = 2.3 / zero;
double b = -0.55 / zero;
assert(true == bdlb::Float::isZero(zero));
assert(true == bdlb::Float::isInfinite(a));
assert(true == bdlb::Float::isInfinite(b));
@ k_INFINITE
Definition bdlb_float.h:227
@ k_ZERO
Definition bdlb_float.h:224
static bool isZero(float number)
static FineClassification classifyFine(float number)
static bool isInfinite(float number)
@ k_NEGATIVE_INFINITY
Definition bdlb_float.h:247
@ k_POSITIVE_INFINITY
Definition bdlb_float.h:246
static Classification classify(float number)

Note that the sign rules apply as usual:

double nzero = -0.0;
double bn = -0.55 / nzero;

The result of multiplying infinity by infinity is also infinity, but the result of multiplying infinity by zero is an indeterminate value (quiet NaN):

double c = a * b;
double d = a * zero;
assert(true == bdlb::Float::isInfinite(c));
assert(false == bdlb::Float::isInfinite(d));
assert(true == bdlb::Float::isNan(d));
assert(true == bdlb::Float::isQuietNan(d));
assert(false == bdlb::Float::isSignalingNan(d));
static bool isNan(float number)
static bool isQuietNan(float number)
static bool isSignalingNan(float number)

Quiet NaNs propagate such that further calculations also yield quiet NaNs:

double g = d - 3.4e12;
assert(false == bdlb::Float::isInfinite(g));
assert(true == bdlb::Float::isNan(g));
assert(true == bdlb::Float::isQuietNan(g));

We can also detect whether a value has full precision (normal) or is so small (close to zero) that precision has been lost (subnormal):

double e = -10.0 / 11.0; // Full precision
double f = e / DBL_MAX; // Lost precision
assert(true == bdlb::Float::isNormal(e));
assert(false == bdlb::Float::isSubnormal(e));
assert(false == bdlb::Float::isNormal(f));
assert(true == bdlb::Float::isSubnormal(f));
@ k_NORMAL
Definition bdlb_float.h:225
@ k_SUBNORMAL
Definition bdlb_float.h:226
static bool isNormal(float number)
static bool isSubnormal(float number)

The Classification enumeration type is designed so that each classification occupies a separate bit. This makes it easy to test for multiple classifications in one test. For example, if we are interested in very that zero or denormalized (i.e., very small), we can detect both conditions with a single mask:

assert(0 != (SMALL_MASK & bdlb::Float::classify(0.0)));
assert(0 != (SMALL_MASK & bdlb::Float::classify(f)));
assert(0 == (SMALL_MASK & bdlb::Float::classify(e)));

Note, however, that although we can create a mask with several classification bits, a single number belongs to only one classification and the return value of classify will have only one bit set at a time.