1

I am learning c programming language and am figuring out format specifiers, but it seems as if double and %f are not working corectly.

Here is my code

#include <stdio.h>
int main(void)
{ 
    double a = 15.1234567899876;
    printf("%13.10f", a);
}

In my textbook it's stated that in "%13.10f" 13 stands for total number of digits we want to be printed(including dot) and 10 is number of decimals. So i expected to get 15.1234567899 but didn't.

After running it I get 15.1234567900. It's not just not enough decimals, but decimals are not printed correctly. Variable a has 8 after 7 and before 9, but printed number does not.

Can someone please tell me where am I wrong.

Thank you. Lp

Barmar
  • 741,623
  • 53
  • 500
  • 612
jeaq
  • 43
  • 3
  • 1
    `%f` is for `float`. Use `%lf` for `double`. Didn't your textbook mention this? – Barmar Jan 23 '23 at 23:59
  • No, but have tried(found on net). Still the same – jeaq Jan 24 '23 at 00:01
  • also see [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken), not every conceivable number can be fully represented in a finite amount of bits. – yano Jan 24 '23 at 00:02
  • 5
    @Barmar When a `float` is passed to a variadic function like `printf`, it is promoted to `double`. So `%f` and `%lf` do exactly the same thing, and either can be used with `double` or with `float` arguments. – user3386109 Jan 24 '23 at 00:04
  • 3
    @user3386109 Oops, was thinking of `scanf`. – Barmar Jan 24 '23 at 00:04
  • 1
    @Barmar Yep, when using `printf`, I always use `%f` for `float`, and `%lf` for `double` just so I don't get things wrong when I use `scanf`. – user3386109 Jan 24 '23 at 00:07
  • 1
    @yano True, but that's not the problem this time. – Steve Summit Jan 24 '23 at 00:21

1 Answers1

6

printf is supposed to round the result to the number of digits you asked for.

  you asked: 15.1234567899876
    you got: 15.1234567900
digit count:    1234567890

So printf is behaving correctly.

You should beware, though, that both types float and double have finite precision. Also their finite precision is as a number of binary bits, not decimal digits. So after about 7 digits for a float, and about 16 digits for a double, you'll start seeing results that can seem quite strange if you don't realize what's going on. You can see this if you start printing more digits:

printf("%18.15f\n", a);

  you asked: 15.1234567899876
    you got: 15.123456789987600

So that's okay. But:

printf("%23.20f\n", a);

  you asked: 15.1234567899876
    you got: 15.12345678998759979095

Here we see that, at the 15th digit, the number actually stored internally begins to differ slightly from the number you asked for. You can read more about this at Is floating point math broken?


Footnote: What was the number actually stored internally? It was the hexadecimal floating-point number 0xf.1f9add3b7744, or expressed in C's %a format, 0x1.e3f35ba76ee88p+3. Converted back to decimal, it's exactly 15.1234567899875997909475699998438358306884765625. All those other renditions (15.1234567900, 15.123456789987600, and 15.12345678998759979095) are rounded to some smaller number of digits. The internal value makes the most sense, perhaps, expressed in binary, where it's 0b1111.0001111110011010110111010011101101110111010001000, with exactly 53 significant bits, of which 52 are explicit and one implicit, per IEEE-754 double precision.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • Yeah, I have tried this, then read that double can store up to 18 decimals or in this case 15(when 15 and dot included). – jeaq Jan 24 '23 at 01:11
  • But if I haven't, this would be very helpful. Thank you very much. – jeaq Jan 24 '23 at 01:11
  • 1
    Re “both types `float` and `double` have finite precision”: As contrasted with all the other standard types which do not? – Eric Postpischil Jan 24 '23 at 02:14
  • @EricPostpischil: `int` can exactly represent every single value in its range and category of numbers it supports. So in a sense it has infinite precision ;-) – Joachim Sauer Jan 25 '23 at 13:42
  • @JoachimSauer: `float` and `double` exactly represent each number in the sets of numbers they represent. E.g., .375 represents exactly ⅜. Would you say `float` and `double` have infinite precision? – Eric Postpischil Jan 25 '23 at 13:52
  • @EricPostpischil *float and double exactly represent each number in the sets of numbers they represent.* Tautology of the day! – Steve Summit Jan 25 '23 at 13:57
  • @SteveSummit: Not quite, because some (too many) people assume a floating-point number `x` represents all the numbers in some interval `(x-e, x+e)`. For them, the set of numbers that `float` represents would include every real number in [−FLT_MAX, +FLT_MAX], and it would represent almost all of them approximately, not exactly. Of course, this is not what the IEEE-754 standard specifies, so saying that `float` and `double` exactly represent each number in the sets of numbers they represent is asserting the IEEE-754 model should be used and the approximation model is wrong. – Eric Postpischil Jan 25 '23 at 14:01
  • @EricPostpischil Very true, and there's more I would say, but to avoid getting too chatty in a comment thread to which it doesn't really apply, I'll defer. – Steve Summit Jan 25 '23 at 14:07