|
Boost : |
From: Paul A. Bristow (boost_at_[hidden])
Date: 2002-09-04 15:20:16
> On a detail, Paul Bristow noted
> that PI is only defined to 21 decimal digits, which might be insufficient
> for some potential uses. Why is it not just defined to 40 decimal digits,
> sufficient for any foreseable floating point hardware,
> even allowing for the known need for a few extra digits - see Kahan's
paper.
> We should be able to assume that the compiler will convert this to
> the best representation that is possible for the floating point type,
> (if it doesn't then it is not compliant).
> Then shouldn't + and - numeric_limits epsilon, pred and succ,
> or nextafter(x, +inf) and (x,-inf) function provide the pi() interval
> values?
>Sylvain Pion replied:
>The C++ standard doesn't guarantee that a decimal notation is rounded to
>the nearest (float/double) value.
Can you quote chapter and verse on this? In practice the only compiler I use
certainly does PROVIDED you have enough decimal digits.
I have run some semi-exhaustive tests to show that you can output
floats and double and read them back in identically.
> This prevents from defining PI (the
>lower/upper value of the smallest interval containing PI) the way you
suggest.
>Guillaume first implemented a version which specified exactly the
> bits of the lower/upper values, using casts with long long.
> It was not very clean.
>Then I found the current solution, which is guaranteed to do what we want,
>provided that doubles and floats have the minimum precision mandated by
IEEE
>(i.e. 24 and 53 bits of mantissa). For long double, I'd love to provide a
more
>precise interval for PI, but all we can assume portably is that the
precision
>is >= the precision of doubles, hence I kept the same value, because
providing
>more precision would not guarantee the correct rounding, hence might give
an
>interval not containing PI.
extract from /interval/constant.hpp follows:
// These constants should be exactly computed.
// Decimal representations wouldn't do it since the standard doesn't
// specify the rounding (even nearest) that should be used.
static const float pi_f_l = 13176794.0f/(1<<22);
static const float pi_f_u = 13176795.0f/(1<<22);
static const double pi_d_l = (3373259426.0 + 273688.0 / (1<<21)) / (1<<30);
static const double pi_d_u = (3373259426.0 + 273689.0 / (1<<21)) / (1<<30);
Which is ingenious but not entirely portable. And lacking for long double,
so far.
I believe that nextafterf, nextafter and nextafterl may provide a better
way.
(They can provide floating point values one least significant bit less and
more).
Is their status in C++ clear (new C proposes them as I recall from PJPs
note)?
Are they available on most systems?
Can we use numeric_limits:: epsilon?
Other suggestions?
Paul
Dr Paul A Bristow, hetp Chromatography
Prizet Farmhouse, Kendal, Cumbria, LA8 8AB UK
+44 1539 561830 Mobile +44 7714 33 02 04
mailto: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