13

equivalent to log10(2^24) ≈ 7.225 decimal digits

Wikipedia

Precision: 7 digits

MSDN

6

std::numeric_limits<float>::digits10

Why numeric_limits return 6 here? Both Wikipedia and MSDN report that floats have 7 decimal digits of precision.

phuclv
  • 37,963
  • 15
  • 156
  • 475
liori
  • 40,917
  • 13
  • 78
  • 105
  • 1
    I guess you meant std::numeric_limits::digits10, right ? – Scharron Jul 22 '10 at 15:07
  • @Scharron: Right, thank you for spotting this. Copy&Paste mistake. – liori Jul 22 '10 at 15:18
  • possible duplicate of [Is the most significant decimal digits precision that can be converted to binary and back to decimal without loss of significance 6 or 7.225?](http://stackoverflow.com/questions/30688422/is-the-most-significant-decimal-digits-precision-that-can-be-converted-to-binary) – Wandering Fool Aug 25 '15 at 14:33
  • See also [How to calculate float type precision and does it make sense?](https://stackoverflow.com/questions/61609276) – Steve Summit Jan 17 '23 at 13:25

2 Answers2

19

If in doubt, read the spec. The C++ standard says that digits10 is:

Number of base 10 digits that can be represented without change.

That's a little vague; fortunately, there's a footnote:

Equivalent to FLT_DIG, DBL_DIG, LDBL_DIG

Those are defined in the C standard; let's look it up there:

number of decimal digits, q, such that any floating-point number with q decimal digits can be rounded into a floating-point number with p radix b digits and back again without change to the q decimal digits.

So std::numeric_limits<float>::digits10 is the number of decimal digits such that any floating-point number with that many digits is unchanged if you convert it to a float and back to decimal.

As you say, floats have about 7 digits of decimal precision, but the error in representation of both fixed-width decimals and floats is not uniformly logarithmic. The relative error in rounding a number of the form 1.xxx.. to a fixed number of decimal places is nearly ten times larger than the relative error of rounding 9.xxx.. to the same number of decimal places. Similarly, depending on where a value falls in a binade, the relative error in rounding it to 24 binary digits can vary by a factor of nearly two.

The upshot of this is that not all seven-digit decimals survive the round trip to float and back, but all six digit decimals do. Hence, std::numeric_limits<float>::digits10 is 6.

There are not that many six and seven digit decimals with exponents in a valid range for the float type; you can pretty easily write a program to exhaustively test all of them if you're still not convinced.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
  • reg. "but all six digit decimals do" what about 0.3 (decimal )? can you kindly elaborate more on those kind of numbers ? – Shmil The Cat May 08 '14 at 19:03
  • 2
    0.3 converted to float (assuming IEEE-754 single-precision here) is exactly `0.300000011920928955078125`. When that value is rounded to six decimal digits, the result is 0.3, so it is unchanged when float and back to decimal with six digits. This is true for all six-digit decimals in the representable range of `float`. – Stephen Canon May 09 '14 at 15:59
  • By fixed-width decimals, you mean [fixed-point numbers](http://en.wikipedia.org/wiki/Q_%28number_format%29) or integral types? – legends2k Aug 25 '15 at 05:27
  • @legends2k: Decimal character sequences with a fixed number of digits, or the or the exact rational numbers represented by them. – Stephen Canon Aug 25 '15 at 21:35
2

It's really only 23 bits in the mantissa (there's an implied 1, so it's effectively 24 bits, but the 1 obviously does not vary). This gives 6.923689900271567 decimal digits of precision, which is not quite 7.

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • Not obviously. All normalized numbers have this implied 1. But your comment reminded me of denormalized numbers, which do have less precision bits. Thanks. – liori Jul 22 '10 at 15:20