16

Can someone explain this behavior? I am well aware of machine-level representation of floating point numbers. This seems to be related to printf and its formats. Both numbers are represented exactly by floating-point notation (check: multiplying by 64 gives an integer).

#include <stdio.h>
#include <iostream>
using namespace std;

int main() {
  double x1=108.765625;
  printf("%34.30f\n", x1);
  printf("%9.5f\n", x1);
  printf("%34.30f\n", x1*64);

  double x2=108.046875;
  printf("%34.30lf\n", x2);
  printf("%9.5f\n", x2);
  printf("%34.30f\n", x2*64);
}

Output:

> 108.765625000000000000000000000000
> 108.76562
> 6961.000000000000000000000000000000
> 108.046875000000000000000000000000
> 108.04688
> 6915.000000000000000000000000000000

Note, the first number gets rounded down, and the second one gets rounded up.

phuclv
  • 37,963
  • 15
  • 156
  • 475
user443854
  • 7,096
  • 13
  • 48
  • 63
  • 1
    You might be interested in my article http://www.exploringbinary.com/inconsistent-rounding-of-printed-floating-point-numbers/ . Some implementations use "round-half-away-from-zero" instead of "round-half-to-even". – Rick Regan Apr 28 '12 at 17:19
  • 1
    It appears that Microsoft changed their default rounding behaviour some time between VS 2010 and VS2015. I just upgraded from one to the other and got some very annoying and subtle bugs. [This blog](https://blogs.msdn.microsoft.com/vcblog/2014/06/18/c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/) is probably meant to highlight the change, but you'd be forgiven for missing it entirely. – omatai Oct 10 '16 at 04:52
  • it depends on implementation [Rounding differences on Windows vs Unix based system in sprintf](http://stackoverflow.com/q/4649554/995714), [C++ Rounding behavior consistency for ties with sprintf](http://stackoverflow.com/q/31142600/995714) – phuclv Nov 02 '16 at 04:29

2 Answers2

20

It's "round half to even" or "Banker's rounding". The last digit of the rounded representation is chosen to be even if the number is exactly half way between the two.

http://linuxgazette.net/144/misc/lg/a_question_of_rounding_in_issue_143.html:
"For the GNU C library, the rounding rule used by printf() is "bankers rounding" or "round to even". This is more correct than some other C libraries, as the C99 specification says that conversion to decimal should use the currently selected IEEE rounding mode (default bankers rounding)."

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
0

The %9.5f output gives the number with 5 digits after the decimal dot which is the nearest of the source number.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • The point of the question, I believe, is: what if the source number is exactly halfway between two possible outputs? – Spike0xff Dec 11 '19 at 21:09