I had/have some confusion regarding rounding a float/double variable to the nearest integer. While googling, I came across this cppreference page for rounding. On that page, it says:
float round ( float arg ); // (1)
float roundf( float arg ); // (2)
double round ( double arg ); // (3)
long double round ( long double arg ); // (4)
double round ( IntegralType arg ); // (5)
Here, I don't understand why is the return value type float, double, or long double? For example, if I have a variable float x and 2.5 <= x < 3.5 then its rounded value is 3. That can be represented using just an int, right? So, why is the return value type of std::round not an int (or long it for long double)?
On that page, it also says:
1-5) Computes the nearest integer value to arg (in floating-point format), rounding halfway cases away from zero, regardless of the current rounding mode.
So, what does exactly "integer value to arg (in floating-point format)" mean?
To understand this std::round, I did one small experiment:
int main(int argc, char const *argv[]) {
float var = 3.14;
int rounded_var_int = std::round(var);
float rounded_var_float = std::round(var);
std::cout << rounded_var_int << ", " << rounded_var_float << std::endl; // 3, 3
return 0;
}
However, this made me even more confused because everything ran just fine.
So, the last question:
In the above code, int rounded_var_int = std::round(var) is just fine or do I need to explicitly cast it to int e.g. int rounded_var_int = static_cast<int>(std::round(var)) to avoid any potential bug(s)?
Why is the return value type of std::round not an integer?
Because the representable range of floating point types generally exceed the range of fundamental integer types and thus those integer types cannot represent all potential return values.
Besides finite rounded values that exceed the range of integer types, other problematic values are infinities, not-a-number values, negative zero which are returned without change.
rounded value is 3. That can be represented using just an int, right?
This value can be represented using int. But being able to represent one, or some of the values isn't sufficient. The return type should be able to represent all rounded values. And that isn't generally achievable with int.
In the above code,
int rounded_var_int = std::round(var)is just fine or do I need to explicitly cast it to int e.g.int rounded_var_int = static_cast<int>(std::round(var))to avoid any potential bug(s)?
Floating point types are implicitly convertible to integer types. The result of the implicit conversion is the same as the result of the static cast.
It is a narrowing conversion. Neither implicit nor explicit conversion is safe in the sense that if the floating point value is outside of representable range, then the behaviour of the program is undefined. Both conversions are safe in the sense that if the value is representable, then the value will remain unchanged by the conversion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With