
Boost : 
Subject: [boost] MS VC10 std::numeric_limits<float>::max_digits10 is wrong for float
From: Paul A. Bristow (pbristow_at_[hidden])
Date: 20110606 10:45:53
Inexplicably, MS for VS 10 have chosen std::numeric_limits<float>::max_digits10 == 8 for VS 10
rather than 9, when the formula
max_digits10 = 2 + std::numeric_limits<FPT>::digits * 3010/10000;
and values have been known for 30 years.
std::numeric_limits<T>:: max_digits10; is 'new for C++0X'.
Briefly, max_digits10 is the number of decimal digits that you need to output to make sure that a
one least significant bit (ULP) change produces a different decimal digit string. Any more digits
are just noise with no useful information.
Using max_digits10 rather than the formula above may be more efficient, and is certainly very much
clearer.
"Executive Summary"
================
Don't use max_digits10 for float or floatingpoint template types for MS VS  yet!
You can safely (and very usefully) use
cout.precision(std::numeric_limits<double>::max_digits10);
when you want to be sure that all significant decimal digits are output.
GCC provides the correct values of 9 for float (and 17 for double).
The Fuller Story
===========
This might affect anyone planning to use VS10 and this new (and very useful numeric_limits value)
with builtin *type float, or a floatingpoint template type*, potentially, for example, with Boost
Lexical_cast, Serialization. Round tripping would be 1 bit wrong in perhaps 1/3 of cases! If
max_digits10 was used, Boost.Test might detect values that are different, but are reported to be the
same, for example. As far as I know, none of these utilities yet try to use max_digits10.
Mercifully, this fault only affects type T = float (not the most popular double or long double), and
only in new code that uses the 'new for C++0X' numeric_limits<T>:: max_digits10. Other types like
double and long double (and possibly user defined types that specialize numeric_limits) are, I
believe, correct.
So you can safely (and very usefully) use
cout.precision(std::numeric_limits<double>::max_digits10);
when you want to be sure that all significant decimal digits are output.
(If you want this to be 'Boost portable' you will have to use the inscrutably named
BOOST_NO_NUMERIC_LIMITS_LOWEST
as a proxy for "C++0x numeric_limits before using newforC++0X max_digits10. Unless we add yet
another macro for max_digits10? Groan.).
The workaround is to continue to use the welltried and test Kahan formula
max_digits10 = 2 + std::numeric_limits<FPT>::digits * 3010/10000;
Reported and confirmed as
https://connect.microsoft.com/VisualStudio/feedback/details/668921/stdnumericlimitsfloatmaxdigi
ts10valueof8iswrongandshouldbe9
(It might help if, you could confirm you can 'reproduce' this too).
I trust this mistake will be corrected pronto  but I'm not holding my breath :(
I will post again if it is resolved.
Paul
 Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 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