Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Tolerance-based comparisons
PrevUpHomeNext

Assertions in the Unit Test Framework use two kinds of comparison. For u being close to zero with absolute tolerance eps:

abs(u) <= eps; // (abs)

For u and v being close with relative tolerance eps:

   abs(u - v)/abs(u) <= eps
&& abs(u - v)/abs(v) <= eps; // (rel)

For rationale for choosing these formulae, see section Floating point comparison algorithms.

Assertion BOOST_TEST (when comparing floating-point numbers) uses the following algorithm:

  • When either value u or v is zero, evaluates formula (abs) on the other value.
  • When the specified tolerance is zero, performs direct (native) comparison between u and v.
  • Otherwise, performs formula (rel) on u and v.
[Note] Note

Therefore in order to check if a number is close to zero with tolerance, you need to type:

BOOST_TEST(v == T(0), tt::tolerance(eps));

The compatibility assertions BOOST_<level>_CLOSE and BOOST_<level>_CLOSE_FRACTION perform formula (rel).

The compatibility assertion BOOST_<level>_SMALL performs formula (abs).

The Unit Test Framework also provides unary predicate small_with_tolerance and binary predicate predicate close_at_tolerance that implement formula (abs) and (rel) respectively.

Tolerance in operator<

Tolerance-based computations also apply to operator< and other relational operators. The semantics are defined as follows:

  • less-at-tolerance <==> strictly-less and not close-at-tolerance
  • greater-at-tolerance <==> strictly-greater and not close-at-tolerance
  • less-or-equal-at-tolerance <==> strictly-less or close-at-tolerance
  • greater-or-equal-at-tolerance <==> strictly-greater or close-at-tolerance
[Note] Note

This implies that the exactly one of these: u < v, u == v, u > v, passes with BOOST_TEST at any given tolerance.

[Caution] Caution

Relation less-at-tolerance is not a Strict Weak Ordering as it lacks the transitivity of the equivalence; using it as predicate in std::map or any order-based STL algorithm would result in undefined behavior.


PrevUpHomeNext