1

I used to think that float can use max 6 digit and double 15, after comma. But if I print limits here:

typedef std::numeric_limits<float> fl;
typedef std::numeric_limits<double> dbl;

int main()
{
    std::cout << fl::max_digits10 << std::endl;
    std::cout << dbl::max_digits10 << std::endl;
}

It prints float 9 and double 17?

markzzz
  • 47,390
  • 120
  • 299
  • 507
  • 10 binary digits? – Vivick Nov 04 '17 at 10:58
  • 1
    `float can use max 6 digit and double 15, after comma` is incorrect. The precision is 15 digits which counts all the significant numbers, not only the ones after decimal point – phuclv Nov 04 '17 at 11:07
  • @LưuVĩnhPhúc: 15 digit in decimal base? max() on double will print `2.22507e-308` which is way more than 15 digits. – markzzz Nov 04 '17 at 11:22
  • @markzzz as I said, it's 15 **significant** digits. `2.22507e-308` has only 6 – phuclv Nov 04 '17 at 11:27
  • @LưuVĩnhPhúc I'm not following you. If I insert `2.22507e-308` on http://www.exploringbinary.com/floating-point-converter/ I got a decimal number with 313 digit after the comma. WAY larger than total 15 :O – markzzz Nov 04 '17 at 11:30
  • 1
    @markzz 313 digits, of which only the first 15 are accurate. The number 17 includes the period and the sign symbol. – Michaël Roy Nov 04 '17 at 11:36
  • 2
    @markzzz "Significant digit" doesn't mean "digit after the comma". –  Nov 04 '17 at 11:37
  • If you learn how a floating point is stored in memory (mantissa + exponent + sign) you will probably understand it better – from56 Nov 04 '17 at 11:44
  • Similar issue in C to [Printf width specifier to maintain precision of floating-point value](https://stackoverflow.com/q/16839658/2410359) – chux - Reinstate Monica Nov 05 '17 at 06:38

3 Answers3

3

You're confusing digits10 and max_digits10.

If digits10 is 6, then any number with six decimal digits can be converted to the floating point type, and back, and when rounded back to six decimal digits, produces the original value.

If max_digits10 is 9, then there exist at least two floating point numbers that when converted to decimal produce the same initial 8 decimal digits.

digits10 is the number you're looking for, based on your description. It's about converting from decimal to binary floating point back to decimal.

max_digits10 is a number about converting from binary floating point to decimal back to binary floating point.

  • See also the handy table "Digit Ranges For Round-Trips To and From IEEE Binary Floating-Point" at the [Exploring Binary](http://www.exploringbinary.com/number-of-digits-required-for-round-trip-conversions/) blog. – njuffa Nov 04 '17 at 17:14
2

From cppreference:

Unlike most mathematical operations, the conversion of a floating-point value to text and back is exact as long as at least max_digits10 were used (9 for float, 17 for double): it is guaranteed to produce the same floating-point value, even though the intermediate text representation is not exact. It may take over a hundred decimal digits to represent the precise value of a float in decimal notation.

For example (I am using http://www.exploringbinary.com/floating-point-converter/ to facilitate the conversion) and double as the precision format:

1.1e308 => 109999999999999997216016380169010472601796114571365898835589230322558260940308155816455878138416026219051443651421887588487855623732463609216261733330773329156055234383563489264255892767376061912596780024055526930962873899746391708729279405123637426157351830292874541601579169431016577315555383826285225574400

Using 16 significant digits:

1.099999999999999e308 => 109999999999999897424000903433019889783160462729437595463026208549681185812946033955861284690212736971153169019636833121365513414107701410594362313651090292197465320141992473263972245213092236035710707805906167798295036672550192042188756649080117981714588407890666666245533825643214495197630622309084729180160

Using 17 significant digits:

1.0999999999999999e308 => 109999999999999997216016380169010472601796114571365898835589230322558260940308155816455878138416026219051443651421887588487855623732463609216261733330773329156055234383563489264255892767376061912596780024055526930962873899746391708729279405123637426157351830292874541601579169431016577315555383826285225574400

which is the same as the original

More than 17 significant digits:

1.09999999999999995555e308 => 109999999999999997216016380169010472601796114571365898835589230322558260940308155816455878138416026219051443651421887588487855623732463609216261733330773329156055234383563489264255892767376061912596780024055526930962873899746391708729279405123637426157351830292874541601579169431016577315555383826285225574400

Continue to be the same as the original.

Amadeus
  • 10,199
  • 3
  • 25
  • 31
  • But what is `109999999999999997216016380169010472601796114571365898835589230322558260940308155816455878138416026219051443651421887588487855623732463609216261733330773329156055234383563489264255892767376061912596780024055526930962873899746391708729279405123637426157351830292874541601579169431016577315555383826285225574400` from `1.1e308`? – markzzz Nov 04 '17 at 12:17
  • 1
    As quoted: "It may take over a hundred decimal digits to represent the precise value of a float in decimal notation.". It means that it is impossible to represent `1.1e308` accurately – Amadeus Nov 04 '17 at 12:18
  • :O But I can't store that value into a variable as double. I don't get whats its meaning :O `int` max() is `2147483647`. Easy as this. `double` max() output `1.79769e+308` which I don't get the "value"... – markzzz Nov 04 '17 at 12:21
  • Between 2 ints, for example: 10 and 12, there is only one number: 11. Between 2 doubles, for example 10.9 and 11.0, there are infinit numbers. So there is a limit (and imprecision) how the underline format can store the number. And what you are seen is exactly this. `1.1e308` is impossible to represent. The best that the underline format can do is the number showed before – Amadeus Nov 04 '17 at 12:24
  • I know. But doubles are "finit". So after some digits it will round to the next/prev. BUT you are still not reply to my question: which (decimal) number is that `1.79769e+308`? If int can store max the (decimal) number `2147483647`, which (decimal) number can store a double? – markzzz Nov 04 '17 at 12:26
  • It is the max number that you can represent using the IEEE 754 for double representation. Any value greater than that is considered +infinity. You can see here: http://www.binaryconvert.com/result_double.html?hexadecimal=7FEFFFFFFFFFFFFF This is the maxinum value that you can represent using this format – Amadeus Nov 04 '17 at 12:33
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/158215/discussion-between-markzzz-and-amadeus). – markzzz Nov 04 '17 at 12:35
0

There isn't an exact correspondence between decimal digits and binary digits.

IEEE 754 single precision uses 23 bits plus 1 for the implicit leading 1. Double precision uses 52+1 bits.

To get the equivalent decimal precision, use

log10(2^binary_digits) = binary_digits*log10(2)

For single precision this is

24*log10(2) = 7.22

and for double precision

53*log10(2) = 15.95

See here and also the Wikipedia page which I don't find to be particularly concise.

Paul Floyd
  • 5,530
  • 5
  • 29
  • 43