1

I was looking for a method to round float numbers in c++ this morning and I found this answer solve my problem.

However, I notice something unusual to me. When I try to round certain float numbers to two decimal places, it seems like numbers such as 1.075 and 1.895 follow different rounding rules. Specifically, with the following simple code:

#include <iostream>
#include <iomanip>

int main(int argc, char** argv)
{
    float testme[] = { 1.07500, 1.89500, 2.70500, 3.47500};
    std::cout << std::setprecision(2) << std::fixed;

    for(int i = 0; i < 4; ++i)
    {
       std::cout << testme[i] << std::endl;
    }

    return 0;
}

The result I have is

1.08
1.89
2.70
3.47

So 1.075 turns to 1.08 while 1.895 becomes 1.89. This really confused me. I would appreciate some explanation. Thanks!

Eric Chen
  • 49
  • 5
  • 1
    Print more characters and get a better look at how 1.075 and 1.895 are really being represented: https://ideone.com/y52ZLJ – user4581301 Mar 11 '18 at 21:25
  • 1
    Those numbers probably can't be represented exactly in binary, so you never have these numbers. Rounding is then influenced accordingly. – Ulrich Eckhardt Mar 11 '18 at 21:25
  • You are not rounding the numbers. The `std::setprecision(2)` does not round anything. You should be using type `double` instead of `float` and `std::round` or similar if you want to round the number. – Ron Mar 11 '18 at 21:25
  • 1
    Strongly related: [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – user4581301 Mar 11 '18 at 21:27
  • 1
    Sadly upping the size to `double` is not good enough: https://ideone.com/EzKDWY And again with more digits: https://ideone.com/oOpmGe – user4581301 Mar 11 '18 at 21:29

2 Answers2

1

I believe this is an issue with floating-point numbers not being able to precisely represent the number 1.895. The closest floating point value to 1.895 that the computer can store is actually

1.894999980926513671875

which, if rounded to two decimal places, actually should be 1.89, since after looking at the next digit you'd round down.

I managed to get the above number using this tool, which might also come in handy for explaining other values.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
0

Most decimal numbers cannot be represented exactly in binary format, so they have to be rounded. IEEE 754 defines several possibilities for this procedure, I think you see this one (citation from Wikipedia):

Round to nearest, ties to even – rounds to the nearest value; if the number falls midway it is rounded to the nearest value with an even (zero) least significant bit; this is the default for binary floating-point and the recommended default for decimal.

Basically, decimal numbers which end with digit 5 are sometimes rounded up and sometimes rounded down to avoid a statistical drift.

maij
  • 4,094
  • 2
  • 12
  • 28