RE: [boost] Re: Insufficient significant digits using lexical_cast

2003-08-20 Thread Paul A. Bristow


| -Original Message-
| From: [EMAIL PROTECTED]
| [mailto:[EMAIL PROTECTED] Behalf Of Daniel Spangenberg
| Sent: Tuesday, August 19, 2003 9:25 AM
| To: [EMAIL PROTECTED]
| 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::is_specialized
  && std::numeric_limits::radix == 2)
{
  stream.precision(2 + std::numeric_limits::digits * 301/1000);
}
else if(std::numeric_limits::is_specialized
  && std::numeric_limits::radix == 2)
{
  stream.precision(2 + std::numeric_limits::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(lexical_cast(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(lexical_cast(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:[EMAIL PROTECTED]

For the curious I used:

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

return (l == lexical_cast(lexical_cast(l)));
} // test

template  bool tests()
{
if (numeric_limits< T >::is_specialized)
{
cout << numeric_limits< T >::digits << ' ' << numeric_limits< T >::digits10
<< ' ' << 2 + std::numeric_limits::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 ();
tests ();
tests ();
tests ();
tests ();
tests ();
tests ();
tests ();
tests ();
tests ();
tests ();

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] Re: Insufficient significant digits using lexical_cast

2003-08-20 Thread Paul A. Bristow


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

| I think, the correct solution would be the usage of a constant, similar to
| DECIMAL_DIG, which is provided from C99 on. 5.2.4.2.2 says:
|
| "— number of decimal digits, n, such that any floating-point number
| in the widest
| supported floating type with pmax radix b digits can be rounded to a
| floating-point
| number with n decimal digits and back again without change to the value,
|
|  pmax log10 b if b is a power of 10
|  Ceil(1 + pmax log10 b) otherwise
|
| DECIMAL_DIG 10"
|
|
| My personal opinion is: Extend the DECIMAL_DIG definition for any
| floating point type,
| similar to digits10

I agree (and indeed have previously and now suggested) that adding to
numeric_limits:: would be the best solution.

But for the time being to 'fix' lexical cast, I think my suggestion, perhaps
with Daryle's refinement to warn if not IEE754, is at least better than the
existing formula.  I will make a further suggestion when I get a moment to test
it.

Paul

Paul A Bristow, Prizet Farmhouse, Kendal, Cumbria, LA8 8AB  UK
+44 1539 561830   Mobile +44 7714 33 02 04
mailto:[EMAIL PROTECTED]

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] Re: Insufficient significant digits using lexical_cast

2003-08-18 Thread Paul A. Bristow
Agreed - but what do we do if NOT is_iec559?

Give up?  #error "Can only work with IEEE 754!"

Or choose a massive amount of decimal digits?  eg 40?

Paul

Paul A Bristow, Prizet Farmhouse, Kendal, Cumbria, LA8 8AB  UK
+44 1539 561830   Mobile +44 7714 33 02 04
mailto:[EMAIL PROTECTED]


| -Original Message-
| From: [EMAIL PROTECTED]
| [mailto:[EMAIL PROTECTED] Behalf Of Daryle Walker
| Sent: Monday, August 18, 2003 7:05 AM
| To: Boost
| Subject: [boost] Re: Insufficient significant digits using lexical_cast
|
|
| On Sunday, August 17, 2003, at 10:33 PM, Paul A. Bristow wrote:
|
| [SNIP]
| > But you are right that it would be better to check that
| > numeric_limits::digits exists and isn't something silly before using
| > the formula.  With all the built-in floating point types it should be
| > fine, and for other (well) User defined floating point types too.  (I
| > will look at this).
| [TRUNCATE]
|
| I think you need to check numeric_limits::radix since your algorithm
| had a base-2-to-10 conversion (the type may not actually be binary!).
| The algorithm was based off a paper about IEEE-754; if IEEE-754 is a
| requirement, you may have to check for that too (via
| numeric_limits::is_iec559).  Remember that even the built-in
| floating-point types aren't guaranteed to match IEEE-754!
|
| Daryle
|
| ___
| Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
|
|

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] Re: Insufficient significant digits using lexical_cast

2003-08-17 Thread Paul A. Bristow
Sorry about the long post, but that seemed the easiest way.

numeric_limits::digits10 does what it says - the number that are _guaranteed_ to
be correct on output,
but that isn't what one usually wants for all _significant_ on input (and I
suggest again another numeric_limits::significant_digits10 which is what you get
from the formaula below).

But you are right that it would be better to check that numeric_limits::digits
exists and isn't something silly before using the formula.  With all the
built-in floating point types it should be fine, and for other (well) User
defined floating point types too.  (I will look at this).

But using +3 instead would be 1 decimal digit too many for most of the FP types.
Since it is done at compile time, getting it 'just right' with the formula below
shouldn't cost anything at run-time.

Incidentally a suitable sort of test is

float const aFloat = any_value;

if (aFloat != lexical_cast(lexical_cast(aFloat )))
(
// problem
}

I think from previous experience that this can be shown to be true for ALL
possible float values (for 32 bit representations) but it would take too long to
test all doubles (assuming 64 bit representation).

HTH

Paul

Paul A Bristow, Prizet Farmhouse, Kendal, Cumbria, LA8 8AB  UK
+44 1539 561830   Mobile +44 7714 33 02 04
mailto:[EMAIL PROTECTED]





| -Original Message-
| From: [EMAIL PROTECTED]
| [mailto:[EMAIL PROTECTED] Behalf Of Daryle Walker
| Sent: Tuesday, August 12, 2003 8:56 AM
| To: Boost
| Subject: [boost] Re: Insufficient significant digits using lexical_cast
|
|
| [Paul claims that lexical_cast prints (floating-point) numbers with too
| few precision digits.  Currently, limits::digits10 + 1 is used.  Paul
| wants to change it to "int significant_digits10 = int(ceil(1 +
| limits::digits * log10Two));" where "limits" is the numeric-limits
| traits class and "log10Two" is the base-10 logarithm of 2.]
|
| You used an article on IEEE 754 arithmetic.  Shouldn't you check if the
| number type is compliant with that format?  Or can this work for any
| suitable type?  You also have to check if "limits::digits" is 2!
|
| Looking at the numbers you had, couldn't you just change
| "limits::digits10 + 1" to "limits::digits10 + 3"?  It could be argued
| that there's just a bug in the definitions of "limits::digits10" (it's
| too low).
|
|
| On Saturday, August 9, 2003, at 5:48 PM, Paul A. Bristow wrote:
| [CHOP OFF really long article, with long attachments]
|
| ___
| Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
|
|

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost