Why does printf output float 1.45 with one decimal place, and 1.445 with two decimal places in different behaviors?

Viewed 284
printf("%.1f, %.2f", 1.45, 1.445);

output

1.4, 1.45

1.45 is sliced but 1.445 is rounded.

I found this, Why printf round floating point numbers? Which explained the specification recommands to round the float.

Edit: I tested it with VS2017 (in a C++ project) and Dev-C.

2 Answers

[Edited: I didn't originally print them to quite ridiculous enough levels of precision, so the answer gave incorrect reasoning behind the result.]

If you print them out to ridiculous levels of precision, the truth comes out:

#include <stdio.h>
printf("%20.20f, %20.20f", 1.45, 1.445);

Result:

1.44999999999999995559, 1.44500000000000006217

So, as converted, 1.45 ends up ever so minutely smaller than 1.45, and 1.445 ends up every so slightly greater than 1.445.

So, of course, when we round 1.45, it rounds down, but when we round 1.445, it rounds upward.

double encodes about 264 different values exactly.

Neither 1.45 nor 1.445 are in that large set of 264 values as those decimal values cannot be represented as a dyadic rational values: some integer times a power of 2.

Instead of 1.45, 1.445, nearby values are used:

 1.45  --> 6530219459687219 * 2^-52 or about 1.449999999999999955591079... 
 1.445 --> 6507701461550367 * 2^-52 or about 1.445000000000000062172489...  or 

OP's printf() performed a good job and rounded those values correctly.

printf("%.1f\n%.2f", 1.45, 1.445);
1.4     
1.45
Related