0

My code:

The result of running the following code:

#include <cstdio>

//i define printBits elsewhere but that's not relevant to my question
void printBits(const float f);
void printBits(const double f);

int main(int argc, char **argv) {
  float f=4.2;
  double d=4.2;
  printf("float: %20.20f\n",f);
  printBits(f);
  printf("double: %50.50f\n",d);
  printBits(d);

 return 0;
}

Is:

float: 4.19999980926513671875
0    10000001 00001100110011001100110

double: 4.20000000000000017763568394002504646778106689453125
0 10000000001 0000110011001100110011001100110011001100110011001101

Notice how I set both f and d to 4.2, but the float value is slightly less than 4.2 and the double value is slightly more than 4.2. I understand why the float value is less than 4.2; the 4.2 value gets truncated to a value ~2^-21 less than 4.2. However, I don't understand why the double value is slightly greater than 4.2. I thought that float and double values would just truncate, but it seems that the double value is rounding up rather than down.

In general, do floats and doubles round to the nearest representable value? Do floats and doubles round differently? I've tried searching for this but couldn't find anything relevant.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Bunny
  • 192
  • 1
  • 1
  • 14
  • If you include ``, you're working in C++, not C. Also if you have overloaded functions, you're definitely working in C++ and not C. Don't tag with the wrong language — it irks people and leads to downvotes. – Jonathan Leffler Oct 09 '18 at 04:36
  • 1
    Hopefully someone will come along with a long explanation of how 4.2 is not exactly representable as binary floating point, but that's why. https://stackoverflow.com/questions/588004/is-floating-point-math-broken – Retired Ninja Oct 09 '18 at 04:41
  • 2
    There's a standard cross-reference Q&A on SO — [Is floating-point math broken?](https://stackoverflow.com/questions/588004/) The answer's no, but it doesn't necessarily work the way you expect. – Jonathan Leffler Oct 09 '18 at 04:44

1 Answers1

6

Floating point values are not truncated, they're rounded to the nearest representable value. You've discovered an interesting example where the rounding goes in a different direction depending on the size of the floating point, but this is not uncommon; you can expect the rounding to go up about 50% of the time and down 50% of the time, with some small number of values being exactly representable and not rounded at all. For example 4.25 would be exact.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 2
    I think easily visualizable examples could be useful. For example, if `float` could represent 0, ¼, ½, ¾, and 1, and `double` could represent 0, ⅛, ¼, ⅜, ½, ⅝, ¾, ⅞, and 1, then converting .6 to `float` would round down to ½ (closer to .5 than to .75), but converting .6 to `double` would round up to ⅝ (closer to .625 than to .5). – Eric Postpischil Oct 09 '18 at 13:54