From: Sylvain Pion (pion_at_[hidden])
Date: 2002-09-04 15:59:08
[Paul, I answer publicly again as well.]
On Wed, Sep 04, 2002 at 09:20:16PM +0100, Paul A. Bristow wrote:
> >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.
If my reading of the standard is correct (you never know with these things :),
this is implementation-defined.
The C++ standard [126.96.36.199] says :
" [...] If the scaled value is in the range of representable values for its
type, the result is the scaled value if representable else the larger or
smaller representable value nearest the scaled value, chosen in an
implementation-defined manner. [...] "
Hence all the compilers you have tested might define this to be the rounding
to nearest, but we can't theoretically rely on it :(
> 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.
Yes it's ingenious, I'm proud of it ;-)
long double uses the double version.
The problem is that if we define too many bits, there might be an uncontrolled
rounding, hence buggy interval.
It's true that it's not 100% portable as is, but it could be made to be.
The requirements of the implementation above are :
- int are 32 bits at least.
- double offers the IEEE 754 53 bits precision at least.
- float offers the IEEE 754 24 bits precision at least.
Not a big requirement, you'll have to admit.
And we can adapt the scheme to lower requirements if necessary.
> I believe that nextafterf, nextafter and nextafterl may provide a better way.
But it requires runtime initialization (and probable portability concerns) for
not much gain. Moreover, the intervals would be 2 ulps wide, instead of the
desired optimal 1 ulp.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk