3

I'm completely new to C and I'm trying to complete an assignment. The exercise is to print tan(x) with x incrementing from 0 to pi/2.

We need to print this in float and double. I wrote a program that seems to work, but I only printed floats, while I expected double.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    double x;
    
    double pi;
    pi = M_PI;
     
    for (x = 0; x<=pi/2; x+= pi/20)
    {
        printf("x = %lf, tan = %lf\n",x, tan(x));
        
    }
    
    exit(0);
}

My question is:

  • Why do I get floats, while I defined the variables as double and used %lf in the printf function?

  • What do I need to change to get doubles as output?

scohe001
  • 15,110
  • 2
  • 31
  • 51
Tim
  • 415
  • 2
  • 10
  • 3
    You are not using `float`.The `printf()` format `%lf` is for `long double`. The format `%f` is for `double`, and a `float` value is promoted to `double` when passed to `printf()`. There isn't a format for `float` (unlike with `scanf()`). If you want more decimal places you can do that with for example `%.12f`. – Weather Vane Sep 10 '20 at 18:40
  • 1
    What about the output you’re getting makes you think that doubles aren’t being printed? – Sneftel Sep 10 '20 at 19:37
  • I used an online C compiler and the output I got had 6 decimal places. I know that double precision has 15 decimal digits, so since I didn't see that many decimal digits I thought it was a float. (https://www.geeksforgeeks.org/difference-float-double-c-cpp/) So with the feedback I got here, I know now that my output is double and I can decide with how many digits the output comes. But how do I manipulate the code so that my output is in float notation? – Tim Sep 10 '20 at 20:21
  • There’s no such thing as “float notation”. `float` and `double` do have different precision, but that doesn’t map to an exact number of decimal digits. If you’d like to print a number with more or less digits, or with a fixed number of digits, or in scientific notation, or other modifications, you can change the format specifier; see the documentation of `printf` for details. – Sneftel Sep 12 '20 at 13:58

2 Answers2

6

"...but I only printed floats, while I expected double"

You are actually outputting double values.

float arguments to variadic functions (including printf()) are implicitly promoted to double in general. reference.

So even if your statement

printf("x = %lf, tan = %lf\n",x, tan(x));

were changed to:

    printf("x = %f, tan = %f\n",x, tan(x));

It would still output double as both "%f" and "%lf" are used as double format specifiers for printf() (and other variadic functions).

Edit to address following statement/questions in comments:

"I know that a double notation has 15 digits of [precision]."

Yes. But there is a difference between the actual IEEE 754 specified characteristics of the float/double data types, and the way that they can be _made to appear using format specifiers in the printf() function.

In simplest terms:

  • double has double (2x) the precision of a float.

  • float is a 32 bit IEEE 754 single precision Floating Point Number with 1 bit for the sign, 8 bits for the exponent, and 24* for the value, resulting in 7 decimal digits of precision.

  • double is a 64 bit IEEE 754 double precision Floating Point Number with 1 bit for the sign, 11 bits for the exponent, and 53* bits for the value resulting in 15 decimal digits of precision.

* - including the implicit bit (which always equals 1 for normal numbers, and 0 for subnormal numbers. This implicit bit is not stored in memory), but not the sign bit.

"...But with %.20f I was able to print more digits, how is that possible and where do the digits come from?"

The extra digits are inaccuracies caused by binary representation of analog numbers, coupled with using a width specifier to force more information to display than what is actually represented by the stored value.

Although width specifiers have there rightful place, they can also result in providing misleading results.

ryyker
  • 22,849
  • 3
  • 43
  • 87
  • Thanks for the feedback! If my output is already in double, how do I get it in floats, since the printf function promotes the variables to double? I know that a double notation has 15 digits of pricision. But with %.20f I was able to print more digits, how is that possible and where do the digits come from? – Tim Sep 10 '20 at 20:25
  • 1
    @Terr070 - See edit for detail addressing your comment at bottom of answer. (If this has addressed your questions, consider accepting by clicking hollow check-mark at top of answer.) – ryyker Sep 11 '20 at 18:24
1

Why do I get floats, while I defined the variables as double and used %lf in the printf function?

Code is not getting "floats", output is simply text. Even if the argument coded is a float or a double, the output is the text translation of the floating point number - often rounded.

printf() simply follows the behavior of "%lf": print a floating point value with 6 places after the decimal point. With printf(), "%lf" performs exactly like "%f".

printf("%lf\n%lf\n%f\n%f\n", 123.45, 123.45f, 123.45, 123.45f);
// 123.450000
// 123.449997
// 123.450000
// 123.449997

What do I need to change to get doubles as output?

Nothing, the output is text, not double. To see more digits, print with greater precision.

printf("%.50f\n%.25f\n", 123.45, 123.45f);
// 123.45000000000000284217094304040074348449710000000000
// 123.4499969482421875000000000

how do I manipulate the code so that my output is in float notation?

Try "%e", "%a" for exponential notation. For a better idea of how many digits to print: Printf width specifier to maintain precision of floating-point value.

printf("%.50e\n%.25e\n", 123.45, 123.45f);
printf("%a\n%a\n", 123.45, 123.45f);

// 1.23450000000000002842170943040400743484497100000000e+02
// 1.2344999694824218750000000e+02
// 0x1.edccccccccccdp+6
// 0x1.edccccp+6

printf("%.*e\n%.*e\n", DBL_DECIMAL_DIG-1, 123.45, FLT_DECIMAL_DIG-1,123.45f);
// 1.2345000000000000e+02
// 1.23449997e+02
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256