c++floating-accuracyceil

ceil(double(int)*double) or ceil(float(int*double))?


I had this C++ code:

int x;
double y;

// do sth

int z = ceil(x*y);

If x = 410, y = 1.1, then z = 452 when it should've been 451. I changed to z = ceil(float(x*y)) and it works. My friend suggests z = ceil(double(x)*y) instead. Are there any differences between the 2 definition of z and which one should I use?

Also what does x*y do? I suspect it is equivalent to float(x)*y but I'm not so sure.


Solution

  • How this all works

    x * y simply multiplies the two variables. This implicitly does a type conversion, in this case converting the int value of 410 to the double value 410.0 (because y is a double) before doing the actual multiplication.

    Because of this type conversion, your friend's suggestion is just a more explicit version of what your original code does. It yields the same result, i.e. it will give 452.

    The answer to your question

    If x = 410, y = 1.1, then z = 452 when it should've been 451

    True, by real world calculus. However, doubles and floats in computers have finite precision. If you print with increased precision:

    printf("%.15f\n", (x * y)); // -> 451.000000000000057
    

    You'll agree that when ceiling this, it yields 452. The reason ceil(float(x * y)) works is entirely by accident; because a float has lower precision than a double, this happens to round x * y to 451.000000....

    You can't rely on floating point arithmetic to produce exactly the results you'd expect in the real world, and the ceil can make that very much apparent in scenario's like the one you give. Without further information on the underlying problem you're trying to solve, I can't give further direction on what you could do.