# Why the printf function is able to print 28 decimal digits, if the float has only 24-bits mantissa?

What is exactly printing in the example in the week 2 lecture:

``````float f = 1.0/10.0;
printf("%.28f\n", f);
// prints the following:   0.1000000014901161193847656250
``````

I mean, if float is represented on 32 bits so the precision is approx. 7 decimal digits (24 binary digits), where come from all the additional 21 decimal digits printed out?

[I posted this on reddit last year but rather than just linking it, I thought I'd repost. In that case, they had printed a few more decimals, but the principle is the same.]

A float value has 32 bits to work with:

• 1 bit to hold the sign
• 8 bits to hold the offset exponent ( which is the exponent + 127)
• and 23 bits to hold the significant digits

So, in the case of decimal value 0.1, it is represented in bits by

``````00111101 11001100 11001100 11001101
seeeeeee evvvvvvv vvvvvvvv vvvvvvvv
``````
• s: the sign bit means it's positive
• e: exponent offset: 01111011 (123 in decimal) which means the exponent value is -4
• v: stored value

so, 0.1 decimal is represented as (in binary):

``````1.1001100 11001100 11001101 x 2^-4
``````

then, you can add up all the bit values:

``````0.500000000000000000000000000000 x 0
0.250000000000000000000000000000 x 0
0.125000000000000000000000000000 x 0
0.062500000000000000000000000000 x 1  <--- start here
0.031250000000000000000000000000 x 1
0.015625000000000000000000000000 x 0
0.007812500000000000000000000000 x 0
0.003906250000000000000000000000 x 1
0.001953125000000000000000000000 x 1
0.000976562500000000000000000000 x 0
0.000488281250000000000000000000 x 0
0.000244140625000000000000000000 x 1
0.000122070312500000000000000000 x 1
0.000061035156250000000000000000 x 0
0.000030517578125000000000000000 x 0
0.000015258789062500000000000000 x 1
0.000007629394531250000000000000 x 1
0.000003814697265625000000000000 x 0
0.000001907348632812500000000000 x 0
0.000000953674316406250000000000 x 1
0.000000476837158203125000000000 x 1
0.000000238418579101562500000000 x 0
0.000000119209289550781250000000 x 0
0.000000059604644775390625000000 x 1
0.000000029802322387695312500000 x 1
0.000000014901161193847656250000 x 0
0.000000007450580596923828125000 x 1  <<--- rounded up
``````

``````0.100000001490116119384765625000
``````

which is what you saw when you printed.

The negative powers of 2, when expressed as decimals, are all finite (no recurring), so you won't have any extra digits beyond those needed to make the smallest fractional bit (2^-27).

For more intricate explanation with diagrams, see wikipedia: http://en.wikipedia.org/wiki/Single_precision_floating-point_format

Brenda.

• Thanks for clarifying, it was helpful. However it would be still interesting, how the converting from binary to decimal is computed and which data type is used for that (i.e. to store a decimal value like 0.000000007450580596923828125000 ;) ). – Marek Paralič Aug 24 '15 at 7:27

Per the C99 standard, section 6.5.2.2, paragraph 6

If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions.

Also according to this Wikipedia article (C data types), next to the `float` data type, there is note saying:

%f (promoted automatically to `double` for `printf()`)

So to actually answer your question, you can print more than 7 decimal digits, because your `float` is converted to a `double` behind the scenes.

If this answers your question please accept it by clicking the gray check-mark to the left, so that it becomes green. You can also vote it up by pressing the up arrow above the check-mark.

Edit

Now that I rehearse your question, I think that you mean "where do the garbage values come from?". If so, I'm not sure. Maybe someone else could answer. I will leave my answer here though in case it solves any similar questions, or just so that you learn something new.

• Thank you for the answer and good point - together with Brenda's answer it was helpful. – Marek Paralič Aug 24 '15 at 7:29