0

The following code gets wrong result when using double data type for the result y, why is this? How do I get the correct one when using double?

You can run this code using https://godbolt.org/z/hYvxjW8xT

#include <cstdio>
#include <iostream>


int main()
{
    double MYR = 153.6;
    double MIYR = -153.6;

    double po_size = 0.1;

    printf("MYR: %.4f\n", MYR);
    printf("MIYR: %.4f\n", MIYR);

    printf("po_size: %.4f\n", po_size);

 
    double y =(MYR - MIYR) / po_size;               // should be 3072
    printf("double res: %d\n", int(y));         // 3071 wrong
    float x = (MYR - MIYR) / po_size;           // should be 3072
    printf("float res: %d\n", int(x));          // correct
    
}
  • 2
    Because floating point math is **not** precise! Be aware that not even this most simple 0.1 can be represented exactly as it is periodic in binary. Both 153.6 and -153.6 are as well. So whatever you do you have to fight with rounding errors (apart from some very few exceptions). – Aconcagua Oct 12 '22 at 06:56
  • 1
    If look closely at `y` it'll be something like `3071.99999999999954525264911353588104248046875` which when truncated becomes `3071`. – Ted Lyngmo Oct 12 '22 at 06:57
  • Btw, you could just do `float x = y;` instead of redoing the calculation. `x` would still become `3072.000000...f` – Ted Lyngmo Oct 12 '22 at 07:04
  • Actually the result depends on the rounding mode enabled – rounding towards zero might have yielded a 3071.999xxx float as well, again getting truncated to 3071 ;) – calculating another value might have led to rounding down as well even with same rounding mode enabled (with the bit determining rounding direction being 0). – Aconcagua Oct 12 '22 at 07:09

1 Answers1

0

Floating point math is an approximation. So you get a number that is close to 3072 (3071.999 for example) and then you truncate it and get 3071. Instead, round the number:

printf("double res: %.0f\n", std::round(y));  

And you don't even need the explicit std::round call, since %.0f format specifier implies the rounding:

printf("double res: %.0f\n", y);

This also avoids possible overflow bugs due to the conversion.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93