简体   繁体   中英

Float rounding off error

#include<iostream>

long myround(float f)
{
  if (f >= UINT_MAX) return f;
  return f + 0.5f;
}

int main()
{
  f = 8388609.0f;
  std:cout.precision(16);
  std::cout << myround(f) << std::endl;
}

Output: 8388610.0

I'm trying to make sense of the output. The next floating number larger than 8388609.0 is 8388610 But why the rounded value is not 8388609?

If you change your example to use double then the error disappears. The problem is float is more limited than double in the number of significant digits it can store. Adding 0.5 to your value simply exceeds the precision limits for a float, causing it to preform some rounding. In this case, 8388609.0f + 0.5f == 8388610.0f .

#include<iostream>

long myround(double f)
{
    if (f >= UINT_MAX) return f;
    return f + 0.5;
}

int main()
{
    double f = 8388609.0;
    std::cout.precision(16);
    std::cout << myround(f) << std::endl;
}

If you continue to add digits to your number, it will also eventually fail for double .

Edit: You can test this easily with a static_assert . This compiles on my platform static_assert(8388609.0f + 0.5f == 8388610.0f, ""); . It will likely compile on yours.

IEEE-754 defines several possible rounding modes, but in practice, the one almost always used is "round to nearest, ties to even". This is also known as "Banker's rounding", for no reason anybody can discern.

"Ties to even" means that if the to-be-rounded result of a floating point computation is precisely halfway between two representable numbers, the rounding will be in whichever direction makes the LSB of the result zero. In your case, 8388609.5 is halfway between 8388609 and 8388610, but only the latter has a zero in the last bit, so the rounding is upwards. If you had passed in 8388610.0 instead, the result would be rounded downwards; if you had passed in 8388611.0, it would be rounded upwards.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM