...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Unit of Least Precision or Unit in the Last Place is the gap between two different, but as close as possible, floating-point numbers.
Most decimal values, for example 0.1, cannot be exactly represented as floating-point values, but will be stored as the closest representable floating-point.
Functions are provided for finding adjacent greater and lesser floating-point values, and estimating the number of gaps between any two floating-point values.
The floating-point type (FPT) must have has a fixed number of bits in the representation. The number of bits may set at runtime, but must be the same for all numbers. For example, NTL::quad_float type (fixed 128-bit representation), NTL::RR type (arbitrary but fixed decimal digits, default 150) or Boost.Multiprecision cpp_dec_float andcpp_bin_float are fixed at runtime, but not a type that extends the representation to provide an exact representation for any number, for example XRC eXact Real in C.
The accuracy of mathematical functions can be assessed and displayed in terms
of Unit in
the Last Place, often as a ulps plot or by binning the differences
as a histogram. Samples are evaluated using the implementation under test and
compared with 'known good' representation obtained using a more accurate method.
Other implementations, often using arbitrary precision arithmetic, for example
Wolfram Alpha are one source
of references values. The other method, used widely in Boost.Math special functions,
it to carry out the same algorithm, but using a higher precision type, typically
using Boost.Multiprecision types like cpp_bin_float_quad
for 128-bit (about 35 decimal digit precision), or cpp_bin_float_50
(for 50 decimal digit precision).
When converted to a particular machine representation, say double
,
say using a static_cast
, the value
is the nearest representation possible for the double
type. This value cannot be 'wrong' by more than half a Unit
in the last place (ULP), and can be obtained using the Boost.Math function
ulp
. (Unless the algorithm
is fundamentally flawed, something that should be revealed by 'sanity' checks
using some independent sources).
See some discussion and example plots by Cleve Moler of Mathworks ulps plots reveal math-function accuracy.