Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does casting `std::floor()` and `std::ceil()` to integer type always give the correct result?

I am being paranoid that one of these functions may give an incorrect result like this:

std::floor(2000.0 / 1000.0) --> std::floor(1.999999999999) --> 1
or
std::ceil(18 / 3) --> std::ceil(6.000000000001) --> 7

Can something like this happen? If there is indeed a risk like this, I'm planning to use the functions below in order to work safely. But, is this really necessary?

constexpr long double EPSILON = 1e-10;

intmax_t GuaranteedFloor(const long double & Number)
{
    if (Number > 0)
    {
        return static_cast<intmax_t>(std::floor(Number) + EPSILON);
    }
    else
    {
        return static_cast<intmax_t>(std::floor(Number) - EPSILON);
    }
}

intmax_t GuaranteedCeil(const long double & Number)
{
    if (Number > 0)
    {
        return static_cast<intmax_t>(std::ceil(Number) + EPSILON);
    }
    else
    {
        return static_cast<intmax_t>(std::ceil(Number) - EPSILON);
    }
}

(Note: I'm assuming that the the given 'long double' argument will fit in the 'intmax_t' return type.)

like image 327
hkBattousai Avatar asked Jan 25 '16 16:01

hkBattousai


People also ask

Does ceil return an int?

The ceil() function returns the integer as a double value.

How do you convert floor to INT?

floor() and math. A float value can be converted to an int value no larger than the input by using the math. floor() function, whereas it can also be converted to an int value which is the smallest integer greater than the input using math. ceil() function.

What does casting to an int do?

Casting in python is therefore done using constructor functions: int() - constructs an integer number from an integer literal, a float literal (by removing all decimals), or a string literal (providing the string represents a whole number)

How to use ceil and floor function in C?

Ceil and Floor functions in C++ In mathematics and computer science, the floor and ceiling functions map a real number to the greatest preceding or the least succeeding integer, respectively. floor(x) : Returns the largest integer that is smaller than or equal to x (i.e : rounds downs the nearest integer).


1 Answers

People often get the impression that floating point operations produce results with small, unpredictable, quasi-random errors. This impression is incorrect.

Floating point arithmetic computations are as exact as possible. 18/3 will always produce exactly 6. The result of 1/3 won't be exactly one third, but it will be the closest number to one third that is representable as a floating point number.

So the examples you showed are guaranteed to always work. As for your suggested "guaranteed floor/ceil", it's not a good idea. Certain sequences of operations can easily blow the error far above 1e-10, and certain other use cases will require 1e-10 to be correctly recognized (and ceil'ed) as nonzero.

As a rule of thumb, hardcoded epsilon values are bugs in your code.

like image 62
Sneftel Avatar answered Oct 19 '22 06:10

Sneftel