17

What is the precise meaning of numeric_limits::digits10? Some other related questions in stackoverflow made me think it is the maximum precision of a double, but

  • The following prototype starts working (sucess is true) when precision is greater that 17 ( == 2+numeric_limits::digits10)
  • With STLPort, readDouble==infinity at the end; with microsoft's STL, readDouble == 0.0.
  • Has this prototype any kind of meaning :) ?

Here is the prototype:

#include <float.h>
#include <limits>
#include <math.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
int main(int argc, const char* argv[]) {
  std::ostringstream os;
  //int digit10=std::numeric_limits<double>::digits10; // ==15
  //int digit=std::numeric_limits<double>::digits; // ==53
  os << std::setprecision(17);
  os << DBL_MAX;
  std::cout << os.str();
  std::stringbuf sb(os.str());
  std::istream is(&sb);
  double readDouble=0.0;
  is >> readDouble;
  bool success = fabs(DBL_MAX-readDouble)<0.1;
}
jpalecek
  • 47,058
  • 7
  • 102
  • 144
sthiers
  • 3,489
  • 5
  • 34
  • 47
  • Related: [Decimal precision of floats](http://stackoverflow.com/questions/3310276/decimal-precision-of-floats) and [Is it 6 or 7.22?](http://stackoverflow.com/q/30688422/183120). – legends2k Aug 25 '15 at 07:39

5 Answers5

17

numeric_limits::digits10 is the number of decimal digits that can be held without loss.

For example numeric_limits<unsigned char>::digits10 is 2. This means that an unsigned char can hold 0..99 without loss. If it were 3 it could hold 0..999, but as we all know it can only hold 0..255.

This manual page has an example for floating point numbers, which (when shortened) shows that

cout << numeric_limits<float>::digits10 <<endl;
float f = (float)99999999; // 8 digits
cout.precision ( 10 );
cout << "The float is; " << f << endl;

prints

6
The float is; 100000000
drb
  • 728
  • 8
  • 21
Andrew Stein
  • 12,880
  • 5
  • 35
  • 43
  • Why is there 8 digits instead of 7 in the float example, because it could have been enough to show the problem? Is there another reason behind this ? – Guillaume Paris Dec 27 '13 at 17:08
  • 1
    @Guillaume07 As far as I can tell, all 7 digit *whole* numbers survive the "double->float->double" conversion intact. The smallest whole number that fails is 16777217, which is 8 digits. An explanation of why numeric_limits::digits10 is 6 can be found here http://stackoverflow.com/questions/3310276/decimal-precision-of-floats – Andrew Stein Mar 03 '14 at 18:31
  • @AndrewStein `is the number of decimal digits that can be held without loss` maybe we should say up 2 sign ? after all we can't represent -99 as unsigned char – Shmil The Cat Apr 17 '19 at 14:06
7

numeric_limits::digits10 specifies the number of decimal digits to the left of the decimal point you can represent without a loss of precision. Each type will have a different number of representable decimal values.

Aaron Saarela
  • 3,956
  • 1
  • 19
  • 17
6

See this very readable paper: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2005.pdf

Although DBL_MAX ( = std::numeric_limits::digits10 = 15 digits) is the minimum guaranteed number of digits for a double, the DBL_MAXDIG10 value (= 17 digits) proposed in the paper has the useful properties:

  • Of being the minimum number of digits needed to survive a round-trip to string form and back and get the same double in the end.

  • Of being the minimum number of digits needed to convert the double to string form and show different strings every time you get (A != B) in code. With 16 or fewer digits, you can get doubles that are not equal in code, but when they are converted to string form they are the same (which will give the case where they are different when compared in the code, but a log file will show them as identical - very confusing and hard to debug!)

When you compare values (e.g. by reviewing them manually by diff'ing two log files) we should remember that digits 1-15 are ALWAYS valid, but differences in the 16th and 17th digits MAY be junk.

Warren Stevens
  • 1,047
  • 12
  • 12
6

The '53' is the bit width of the significand that your type (double) holds. The '15' is the number of decimal digits that can be represented safely with that kind of precision.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
DevSolar
  • 67,862
  • 21
  • 134
  • 209
2

digits10 is for conversion: string → double → string
max_digits10 is for conversion: double → string → double

In your program, you are using the conversion (double → string → double). You should use max_digits10 instead of digits10.


For more details about digits10 and max_digits10, you can read:

Daniel Laügt
  • 1,097
  • 1
  • 12
  • 17