Boost logo

Boost :

From: Paul A Bristow (pbristow_at_[hidden])
Date: 2006-11-10 06:30:24


 

| -----Original Message-----
| From: boost-bounces_at_[hidden]
| [mailto:boost-bounces_at_[hidden]] On Behalf Of Gennadiy Rozental
| Sent: 09 November 2006 20:42
| To: boost_at_[hidden]
| Subject: Re: [boost] Boost.Test feature request
|
| Also I would like to hear from
| you the rationale for all the conditions and selected precisions.

My thinking is:

1 The number of digits shown should be only those that are potentially significant for the Floating-point type being reported. For
float 9, double 17, long double - varies.

2 Despite the clutter caused by trailing zeros, these have the advantage of showing the meaningful precision for the value.

3 The precision is very important because many obscure not-equal, and not-quite-close-enough errors involve computation, round-off
errors and unexpected conversions losing accuracy. The last thing we want is error messages saying "{1.2345} and {1.2345} are not
equal": this appears to be nonsense and some users will immediately assume Boost.Test is at fault.

Ideally precision should be std::numeric_limits<T>::max_digits10, as now accepted for C++0X, and this should be defined for ALL
types, built-in as User-defined; but we should not attempt this yet until it becomes standard. However we might consider
designating a BOOST_HAS_MAX_DIGITS10 macro (but not yet defining it) and using this now thus:

#ifdef BOOST_HAS_MAX_DIGITS10 && std::numeric_limits<T>::is_specialized
  precision = std::numeric_limits<T>::max_digits10)
#else
        existing code
#endif

So for the time being - it's already complicated enough;):

For all Decimal types, and this includes User-defined decimal types like NTL::RR, a typical arbitrary but pre-set precision, the
existing std::numeric_limits<T>::digit10 is correct.
Since std::numeric_limits<T>::digits may also be correct, it is essential to test for radix == 10 first. As supplied, NTL::RR does
not have numeric_limits specialized and digits10 is undefined, but users can do this if they wish. However, the precision in bits
is set at compile time, but the displayed digits, effectively digits10, can be altered at run-time.

For built-in floating point types, the formula you are now using, which derives from std::numeric_limits<T>digits, the number of
significand bits, is correct.

For UD floating-point types, provided std::numeric_limits<T>digits is valid (has been specilized, and has had a value assigned (all
unassigned are zero by default), this formula is correct.

If digits is (still) zero, then the most likely reason is a high (but not necessarily fixed at compile time) precision.

For any other radix or where std::numeric_limits<T>::digits = 0 (almost certainly unassigned), we really don't have much to go on.
But the default precision of 6 decimal digits is almost certainly not the most helpful - far too few. So John Maddock has suggested
using the precision of the most accurate built-in long double type std::numeric_limits<long double>::digits. This deals with the
case of a composite type like <complex>. It may give some superflous, but harmless decimal digits, but should never produce an
unhelpful "{1.2345} and {1.2345} are not equal" message.

Ideally the user should always specialize numeric_limits for his type, and assign a suitable value to digits, digits10 and/or
eventually max_digits10.

For integer types, precision is meaningless, so ideally set_precision should not be called at all, or do nothing.

HTH

Paul

---
Paul A Bristow
Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB
+44 1539561830 & SMS, Mobile +44 7714 330204 & SMS
pbristow_at_[hidden]
 

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk