3

I am using C printf to print doubles and found the rounding is inconsistent. Sometimes it will not round up with certain values.

double t = 16.125;
printf("%-10.2lf", t);

This prints 16.12. I thought it would round up to 16.13.

double t = 16.135;
printf("%-10.2lf", t);

This prints 16.14. This is what I thought would happen for all cases.

Sei4or
  • 68
  • 5

1 Answers1

4

The default rounding behaviour is round-half-to-even.

This means:

  • 16.125 is exactly halfway between 16.12 and 16.13, so it rounds (down) to 16.12 (the even one).

  • 16.135 can't be exactly represented by a floating-point number. On my system, it's 16.135000000000001563194018672220408916473388671875. This number is closer to 16.14 than to 16.12, so it rounds to 16.14.

  • 16.375 is exactly halfway between 16.37 and 16.38, so it rounds (up) to 16.38 (the even one).

fesetround allows one to change the default.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Oh that is interesting. The round half to even matches what I am seeing. Why did you use the closest value to 16.14? – Sei4or Sep 13 '22 at 23:46
  • Re "*Why did you use the closest value to 16.14?*", I don't understand the question. I didn't use the closest double to 16.14. That's `16.1400000000000005684341886080801486968994140625`. `printf` produces the string `16.14`. – ikegami Sep 13 '22 at 23:48
  • I meant 16.135, sorry. that closest value to 16.135 will round to 16.14 because 4 is even and 16.135 would also round. I was just wondering why you choose to use the closest value to 16.135. – Sei4or Sep 13 '22 at 23:50
  • @user3386109 Oh it does not? I did not realize the numbers cannot be represented exactly. – Sei4or Sep 13 '22 at 23:51
  • Re "*I was just wondering why you choose to use the closest value to 16.135*", You mean why did the computer choose that? Why wouldn't it? You think it would choose something further away? – ikegami Sep 13 '22 at 23:52
  • @Sei4or try it yourself `printf("%.50f\n", 16.135);` – kikon Sep 13 '22 at 23:53
  • So when I type 16.135 the language is actually representing that with the closest value it can? I do not understand the round half to even algorithm enough to know why it does not qualify. – Sei4or Sep 13 '22 at 23:53
  • @user3386109, Re "*16.135 doesn't qualify for the round-half-to-even*", oh yeah. duh. Fixing – ikegami Sep 13 '22 at 23:53
  • Re "*I do not understand the round half*", If the portion to round is exactly 5, it'll pick the even neighbour – ikegami Sep 13 '22 at 23:54
  • Oh but because of the way the computer represents this number it is not exactly 5 but with 0.375 the computer can represent it exactly and use that rule. – Sei4or Sep 13 '22 at 23:57
  • Thank you for the help. This is a much more complicated system than I expected. The edits to the original answer help clarify a lot @ikegami – Sei4or Sep 14 '22 at 00:00
  • @user3386109 Thank you. I assume the computer cannot represent those numbers exactly because of the way the information is laid out in IEEE 754? – Sei4or Sep 14 '22 at 00:02
  • 4
    The way I like to explain it: 135/1000 is periodic in binary just like 1/3 is periodic in decimal. Therefore, it can't be stored exactly using a floating-point number. 125/1000 (0.001) and 375/1000 (0.011) aren't periodic in binary. – ikegami Sep 14 '22 at 00:02
  • @ikegami Oh that makes a lot of sense. I did not realize that. – Sei4or Sep 14 '22 at 00:07