Boost logo

Boost :

From: Paul A. Bristow (boost_at_[hidden])
Date: 2003-08-20 14:31:22


| -----Original Message-----
| From: boost-bounces_at_[hidden]
| [mailto:boost-bounces_at_[hidden]]On Behalf Of Daniel Spangenberg
| Sent: Tuesday, August 19, 2003 9:25 AM
| To: boost_at_[hidden]
| Subject: [boost] Re: Insufficient significant digits using lexical_cast

In the absence of a C99 or numeric_limits significant decimal digits value
(and don't forget what is needed is effectively an 'unrounded' value with some
'noisy' guard digits at the end, not just digits10)

some tests show that the following

if(std::numeric_limits<Target>::is_specialized
  && std::numeric_limits<Target>::radix == 2)
{
  stream.precision(2 + std::numeric_limits<Target>::digits * 301/1000);
}
else if(std::numeric_limits<Source>::is_specialized
  && std::numeric_limits<Source>::radix == 2)
{
  stream.precision(2 + std::numeric_limits<Source>::digits * 301/1000);
}

uses the correct number of significant decimal digits for ALL builtin bool,
char, int and floating point types:

And a loopback test like:

l == lexical_cast<T>(lexical_cast<string>(l))

is true (correct) for at least some selected values - and I wager a couple of
beers for all non-NaN non-Inf values ;-).

Possibly a comment warning of possible trouble here would be helpful?

// if neither specialized, or unusual radix, then use default stream precision
of 6?
// Warning: a loopback like
// l == lexical_cast<T>(lexical_cast<string>(l)) may be false

I believe a test radix == 2 is appropriate because is_iec599 (IEEE754) would
fail for integer types, which actually work correctly with the above formula.

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]

For the curious I used:

template <typename T> bool test(T l)
{
        cout << l << ' ';
        string sl = lexical_cast<string>(l);
        cout << sl << ' ';
        T ll = lexical_cast<T >(sl);
        cout << ll
                << (l == lexical_cast<T>(lexical_cast<string>(l)))
                // Convert type T to string and back to T.
                << endl; // eg for long 2147483647 2147483647 2147483647true

        return (l == lexical_cast<T>(lexical_cast<string>(l)));
} // test

template <typename T> bool tests()
{
        if (numeric_limits< T >::is_specialized)
        {
        cout << numeric_limits< T >::digits << ' ' << numeric_limits< T >::digits10
                << ' ' << 2 + std::numeric_limits<T>::digits * 301/1000
                << endl;
        }
        else
        {
                cout << "Not specialized!" << endl;
        }
        return // for a few sample values.
                test< T >(numeric_limits< T >::max()) // max
                && test< T >(T(1)) // unity
                && test< T >(T(0)) // zero
                && test< T >(T(-1)) // -1
                && test< T > (numeric_limits< T >::min()); // min
} // tests

and

        tests<bool> ();
        tests<char> ();
        tests<unsigned char> ();
        tests<short> ();
        tests<unsigned short> ();
        tests<int> ();
        tests<long> ();
        tests<unsigned long> ();
        tests<float> ();
        tests<double> ();
        tests<long double> ();


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