Why is double printing the same value as float in C when they have different sizes?

73 views Asked by At

I need to do calculations using π. When I checked precision of M_PI, it only printed 7 decimal digits. So I #defined my own MY_PI. But I am still facing the same problem. double should support 15-17 decimal digits. Why am I only getting 6

#define MY_PI 3.1415926535897932384626433832795028841971
#include<stdio.h>
#include<math.h>
int main()
{
    printf("%f\n%lf\n%20lf\n",M_PI,M_PI,M_PI);
    printf("%d\n%d\n",sizeof(float),sizeof(double));
    printf("%f\n%lf\n%20lf\n",MY_PI,MY_PI,MY_PI);
    return 0;
}

Executing the code results in this,

3.141593
3.141593
            3.141593
4
8
3.141593
3.141593
            3.141593

Process returned 0 (0x0)   execution time : 0.080 s
Press any key to continue.


3

There are 3 answers

0
Eric Postpischil On BEST ANSWER

C does not pass type information about arguments to a function. printf takes all type information from the format string you pass it.

For historical reasons, both %f and %lf tell printf to expect a double argument. Per C 2018 7.21.6.1 8, %f instructs printf:

A double argument representing a floating-point number is converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6;…

Thus six digits are printed merely because that is the default, not because of anything particularly to do with the type. To see more digits, request more digits:

printf("%.60f\n", M_PI);

This will commonly print:

3.141592653589793115997963468544185161590576171875000000000000

Note that %20f requests a field width of 20 characters. A field width is typically used for spacing, to help align columns of data over multiple lines. To satisfy a field width, spaces are used for padding. The code above uses %.60f to request precision, which controls the number of digits produced.

0
Dario.Casciato On

That's because of the precision of printf you are giving it. when using %f or %lf, the printf function always prints only 6 digits after the decimal. You have to tell it how many digits after the decimal you want. It looks like you tried this, but not the right way. you have to add a dot before the number of digits you want to see.

example:

printf("Test: %.20lf", MY_PI);
0
Lundin On
  • Everything passed to variadic functions like printf undergoes implicit argument promotion. In case of float, it always gets promoted to double. So %f and %lf means the same thing. There are only two different versions available to make printf consistent with scanf where %f vs %lf matters.
  • printf caps the amount of decimals to 6 (and rounds the value) unless you tell it otherwise.
  • %20lf only tells how many characters to print (for purposes of alignment/padding with spaces etc). To tell it how many decimals to print, use
    %.20lf with a .. Or if you will a combination, %20.20lf.
  • 1415926535897932384626433832795028841971 is of type double or long double. Casting it to float before passing it to printf will result in the expected loss of precision.

Example (GNU C gcc -lm):

  printf("%.20lf\n%.20lf\n",M_PI, (float)M_PI);

Output:

  3.14159265358979311600
  3.14159274101257324219